UWP/WinRT: как сохранить, а затем восстановить простое текстовое поле для возобновления работы после закрытия?

В этом документе описывается жизненный цикл Приложение Windows 10 UWP, в нем говорится:

Теперь пользователи ожидают, что ваше приложение запомнит свое состояние, когда они будут работать в многозадачном режиме на своем устройстве. Например, они ожидают, что страница будет прокручена до той же позиции, а все элементы управления будут в том же состоянии, что и раньше. Понимая жизненный цикл запуска, приостановки и возобновления работы приложения, вы можете обеспечить такое плавное поведение.

Тем не менее, похоже, не так много документации о том, как это на самом деле достигается. Я полагаю, что все должно быть сохранено вручную разработчиком приложения, а затем воссоздано с нуля при возобновлении работы с использованием любых данных, которые вы спрятали, когда приложение было приостановлено, и все это для того, чтобы создать иллюзию того, что точное состояние памяти приложения никогда не менялось. .

Я пытаюсь разобраться в этом, используя лишь минимальный пример, страницу XAML, не содержащую ничего, кроме TextBox. Однако даже в этой ситуации я немного пытаюсь понять, как достичь цели. Я изложу более общие мысли, но мой конкретный вопрос заключается в том, как сохранить, а затем восстановить простое текстовое поле для возобновления работы после прекращения работы? Я работаю на C++/CX, но приму любую помощь, которую я может получить.

Вот мои мысли по этому поводу:

  • At minimum, obviously the text of the TextBox has to be saved.
    • This could be saved into the ApplicationData::Current->LocalSettings.
    • Одна проблема, которую я сразу же вижу, заключается в том, что в документе, который я цитировал выше, говорится о жизненных циклах, в котором говорится, что приложения должны позаботиться о своем сохранении в течение 5 секунд после сигнала приостановки или завершения работы. Текстовое поле потенциально может содержать много данных, что может привести к отключению сохранения из-за загруженного ввода-вывода, особенно если мы начнем масштабирование за пределы тривиальной ситуации с одним текстовым полем.
    • К счастью, в документе говорится: «Мы рекомендуем использовать для этой цели API-интерфейсы данных приложения, поскольку они гарантированно завершатся до того, как приложение перейдет в состояние «Приостановлено». Дополнительные сведения см. в разделе Доступ к данным приложения с помощью приложения UWP». К сожалению, когда вы переходите по этой ссылке, там нет ничего подходящего, предоставляющего более подробную информацию, и я не могу найти ничего, документирующего это поведение в API. Сохраняя в ApplicationData::Current->LocalSettings, мы защищены от отключения из-за поврежденных или потерянных данных?
  • Once the minimum has been taken care of, next we'll probably need extras like cursor and window position.
    • We can get the cursor position with TextBox->SelectionStart, which as far as I can tell, is undocumented in the API of this usage of returning the current cursor position. This seems an easy fit to also store as an int into ApplicationData::Current->LocalSettings.
    • Как мы можем получить, сохранить и восстановить положение прокрутки окна TextBox?
  • Теперь, когда у нас есть дополнения, как насчет сложных вещей, таких как отмена истории? Я предполагаю, что это невозможно, так как мой вопрос о Stackoverflow о том, как получить доступ к средству отмены TextBox, не получил ответа. Тем не менее, это кажется плохим пользовательским опытом, если они переключаются на другое приложение, возвращаются, думая, что приложение никогда не закрывалось из-за прекрасного и бесшовного восстановления после закрытия, которое мы внедрили, и их история отмен была стерта.
  • Есть ли что-то еще, что нужно сохранить для TextBox, чтобы создать идеальный пользовательский опыт? Я что-то упустил или есть более простой способ сделать все это? Как что-то вроде Microsoft Edge Browser справится со сложным случаем, когда есть десятки вкладок, вводов форм, позиций прокрутки и т. д., которые нужно сохранить за 5 секунд?

person William Jones    schedule 12.08.2015    source источник
comment
Возможно, вы могли бы установить для свойства NavigationCacheMode страницы значение NavigationCacheMode.Required или NavigationCacheMode.Enabled в конструкторе.   -  person tao    schedule 13.08.2015
comment
@tao это хорошее предложение, но оно не подходит для случая, когда ОС решает закрыть приложение. Завершение может быть выполнено из-за того, что приложение неактивно и/или из-за того, что другим приложениям требуется память.   -  person chue x    schedule 13.08.2015
comment
@chuex Вам не нужно сохранять все. Возможно, рассмотрите возможность использования класса SuspensionManager для его реализации.   -  person tao    schedule 13.08.2015


Ответы (1)


Документ жизненный цикл приложения, на который вы ссылаетесь, был обновлен для Windows 10, но, похоже, потерял некоторые важные моменты, которые вас интересуют.

Я нашел старую запись в блоге, Управление жизненным циклом приложения, чтобы ваши приложения всегда оставались живыми, похоже, это послужило источником вдохновения для вашей ссылки.

В сообщении в блоге есть абзац ближе к концу, который гласит:

Сохраняйте нужные данные в нужное время

Всегда сохраняйте важные данные постепенно на протяжении всего жизненного цикла вашего приложения. Поскольку у вашего приложения есть только пять секунд для запуска кода обработчика событий приостановки, вам необходимо убедиться, что важные данные вашего приложения были сохранены в постоянном хранилище к моменту приостановки.

Существует два типа данных, которыми вы можете управлять при написании своего приложения: данные сеанса и данные пользователя. Данные сеанса — это временные данные, которые относятся к текущему опыту пользователя в вашем приложении. Например, текущую акцию, которую просматривает пользователь, текущую страницу, которую пользователь читает в электронной книге, или позицию прокрутки в длинном списке элементов. Пользовательские данные являются постоянными и всегда должны быть доступны пользователю, несмотря ни на что. Например, незавершенный документ, который набирает пользователь, фотография, сделанная в приложении, или прогресс пользователя в вашей игре.

Учитывая вышесказанное, я попытаюсь ответить на ваши вопросы:

как вы сохраняете, а затем восстанавливаете простое текстовое поле для возобновления после завершения?

Когда конечный пользователь вводит текстовое поле, приложение сохраняет содержимое в фоновом режиме в хранилище данных. Чтобы позаимствовать то, как работает программное обеспечение для обработки текстов, вы автоматически сохраняете документ текстового поля. Я бы считал, что содержимое текстового поля — это то, что вышеприведенное сообщение в блоге описывает как пользовательские данные. Поскольку сохранение выполняется вне приостановки, беспокоиться не о временном окне.

Когда ваше приложение возобновляет работу, оно проверяет хранилище данных и загружает любые данные в текстовое поле.

После того, как мы позаботились о минимуме, нам, вероятно, потребуются дополнительные функции, такие как курсор и положение окна.

Я бы учитывал данные сеанса этих элементов и сохранял бы их во время приостановки. Ведь нет необходимости отслеживать эту информацию, пока приложение активно. Пользователю все равно, где был курсор 10 минут назад, когда он начал печатать — ему важна только позиция курсора в момент приостановки.

как насчет сложных вещей, таких как отмена истории?

Я бы рассматривал историю отмен как пользовательские данные и сохранял бы их, пока это происходит (вне приостановки). Другими словами, когда пользователь вводит контент, ваше приложение должно сохранять информацию, необходимую для отмены.

person chue x    schedule 16.08.2015
comment
Спасибо за ответ. Так как же будет выглядеть фактический код для сохранения всего этого? В частности, как вы сохраняете и восстанавливаете положение прокрутки TextBox и историю отмен? - person William Jones; 17.08.2015
comment
Предполагая, что элемент управления предоставляет эту информацию, вы можете записать ее в файл в локальном хранилище приложения. Когда приложение запускается после завершения, вы читаете файл и устанавливаете эти значения. Если элемент управления не предоставляет эту информацию, вам придется свернуть свой собственный элемент управления и предоставить необходимые хуки/методы. Последнее (создание элемента управления для обработки истории отмены), вероятно, слишком широко, чтобы ответить здесь. - person chue x; 17.08.2015