Когда пользователь покидает ваше приложения, оно дезактивируется. Если пользователь использует кнопку «Назад», чтобы вернуться к вашему приложению, вам необходимо восстановить приложение в соответствующее состояние.
В этой части вы узнаете:
- Что такое tombstoning.
- Как восстановить приложения после того, как оно было дезактивировано.
- Когда выполнять другие действия в вашем приложении.
Обзор tombstoning
Ваше приложение может быть прервано и дезактивировано в любой момент, как правило, это происходит, когда пользователь переходит к другому приложению с помощью кнопки «Start». Когда это происходит, ваше приложение должно сохранить свое состояние так, чтобы оно могло быть восстановлено в случае возврата к нему. Однако, изолированное хранилище является слишком медленным для краткосрочного хранения данных о состоянии. Вместо этого, вы кэшируете данные, используя хранящиеся в памяти словари состоянии для того, чтобы быстро сохранить и загрузить данные.
Когда приложение дезактивируется, его процесс может быть остановлен с использованием процедуры, называемой tombstoning (tombstone — надгробная плита), которая сохранит записи приложения в памяти и свяжет их с вашими кэшированными данными о состоянии. Если пользователь переходит обратно в ваше приложение, операционная система перезапускает процесс приложения и передает ему обратно данные о состоянии.
Совет:
Когда работа приложения прерывается, а затем возобновляется, пользователи ожидают продолжения работы с того места, где она была прервана. По этой причине, вы всегда должны реализовывать поддержку tombstoning для любой страницы, которая может изменять свое состояние. Это относится к изменениям состояния настолько сложным, как обновление введённых пользователем данных, или настолько простым, как изменение текущего выделения в списке. Отсутствие поддержки tombstoning может привести к ухудшению юзабилити в лучшем случае и совершенно неожиданному поведению в худшем случае.
Сертификационное требование:
Ваше приложение не должно задерживать или препятствовать возможности пользователю совершить вызов, ответить на входящий вызов или завершить вызов.
Реализация поддержки tombstoning
Для того, чтобы использовать временный кэш, который сохраняется в течение tombstoning, выполните следующие действия:
- Поместите данные о состоянии уровня приложения в свойство PhoneApplicationService.State в событии Deactivated и извлеките данные в обработчике события Activated.
- Поместите данные о состоянии уровня страницы в свойство PhoneApplicationPage.State для каждой страницы в перегрузке метода OnNavigatedFrom и извлеките данные в перегрузке метода OnNavigatedTo.
Совет по улучшению производительности:
Используйте словари состояний для восстановления состояния. Избегайте восстановления состояния из изолированного хранилища или из Интернета.
Приложение Fuel Tracker сохраняет временные состояния уровня страницы в процессе tombstoning, но не имеет данных о состоянии уровня приложений для сохранения. Каждая страница сохраняет данные о состоянии с своё свойство PhoneApplicationPage.State. Например, класс FillupPage содержит объект Fillup, привязанный к некоторым текстовым полям. Этот объект сохраняется на длительное хранение, только когда пользователь нажимает кнопку «Save». Однако, во время tombstoning страница помещает объект в словарь State (состояние) страницы наряду со значением, указывающим, вносил ли пользователь изменения в него, как показано в следующем фрагменте кода. (Реализации кнопки «Save» будет описана в части «Валидация вводимых данных».)
- private const string CURRENT_FILLUP_KEY = "CurrentFillup";
- private const string HAS_UNSAVED_CHANGES_KEY = "HasUnsavedChanges";
- private Fillup currentFillup;
- private bool hasUnsavedChanges;
-
- protected override void OnNavigatedFrom(NavigationEventArgs e)
- {
- base.OnNavigatedFrom(e);
- if (cacheChanges)
- {
- CommitTextBoxes();
- this.State[CURRENT_FILLUP_KEY] = currentFillup;
- this.State[HAS_UNSAVED_CHANGES_KEY] = hasUnsavedChanges;
- }
- }
-
- protected override void OnNavigatedTo(NavigationEventArgs e)
- {
- base.OnNavigatedTo(e);
-
- CarHeader.DataContext = CarDataStore.Car;
-
- DataContext = currentFillup =
- State.ContainsKey(CURRENT_FILLUP_KEY) ?
- (Fillup)this.State[CURRENT_FILLUP_KEY] :
- new Fillup() { Date = DateTime.Now };
-
- hasUnsavedChanges = State.ContainsKey(HAS_UNSAVED_CHANGES_KEY) ?
- (bool)State[HAS_UNSAVED_CHANGES_KEY] : false;
- }
* This source code was highlighted with Source Code Highlighter.В этом коде перегруженный метод OnNavigatedFrom сначала проверяет, должен ли он кэшировать данные о состоянии. Класс FillupPage инициализирует поле cacheChanges в значение true, но устанавливает его в false всегда, когда происходит обычная навигация (то есть, когда пользователь нажимает кнопку «Save» или «Back»). Таким образом, страница кэширует данные только тогда, когда навигация происходит в результате дезактивации.
Если изменения были кэшированы, метод OnNavigatedFrom применяет значения текстовых полей к привязанному (bound) объекту (хранящемуся в поле currentFillup), а затем сохраняет значения currentFillup и hasUnsavedChanges в словарь State. Применение (committing) значения текстового поля необходимо, поскольку привязки данных обычно происходят, когда элемент управления теряет фокус, что не происходит автоматически, когда приложение дезактивируется.
Метод OnNavigatedTo устанавливает элемент CarHeader в свойство DataContext, а затем пытается получить хранящиеся значения из словаря State. Если значения представлены в словаре, они используются для установки свойства DataContext страницы в дополнение к полям currentFillup и hasUnsavedChanges. В противном случае, используются значения по умолчанию.
Данная реализация предоставляет базовую поддержку tombstoning, но не хранит каждый аспект состояния страницы. В частности, эта реализация не сохраняет значение, указывающее, какое текстовое поле находится в фокусе, а также не хранит позицию курсора и состояние выделения текстового поля в фокусе. Важность сохранения этой информации о состоянии зависит от приложения.
Совет:
При реализации поддержки tombstoning не забудьте тщательно её протестировать. Для этого перейдите к каждой странице (с помощью эмулятора или фактического устройства), нажмите кнопку «Start», а затем нажмите кнопку «Назад». Обязательно проверьте каждое состояние каждой странице вашего приложения и убедитесь, что реактивация всегда восстанавливает состояние так, как ожидалось.
Если вы тестируете поддержку tombstoning в эмуляторе в Visual Studio в режиме отладки, вы заметите, что отладчик иногда прерывает соединение, когда вы дезактивируете ваше приложение. В этом случае приложение будет казаться зависшим на «восстанавливающейся» странице, когда вы его повторно активируете. Вы можете решить эту проблему, просто перейдя в Visual Studio и нажав F5 снова. Приложение тогда будет перезагружено и повторно активировано.
Когда выполнять действия в приложении
Вы можете написать код для каждого этапа жизненного цикла приложения. Выше было описано, как реагировать на навигацию по страницам для того, чтобы загружать данные и осуществлять поддержку tombstoning. Ниже будет описан общий жизненный цикл приложения и страницы и указаны общие виды кода, который может быть написан для каждого этапа жизненного цикла.
Приложение Windows Phone запускается, когда пользователь нажимает на иконку или плитку приложения, и закрывается, когда пользователь нажимает кнопку «Назад» на первой странице приложения. Внешние события (например, при нажатии кнопки «Start») могут дезактивировать приложение в любое время, потенциально вызвав его tombstoning и заставляя его завершить работу. Повторная активация перезапускает приложения и дает ему возможность восстановить свое предыдущее состояние. Эти этапы запуска и завершения работы в жизненном цикле представлены в виде событий Launching, Activated, Closing и Deactivated класса PhoneApplicationService.
Как только приложение запущено, стартовая страница открывается автоматически, после чего пользователь может перейти на дополнительные страницы. Если приложение дезактивируется и повторно активируется, происходит переход к ранее активной страницы.
Когда приложение впервые переходит на страницу или переходит обратно на страницу после дезактивации и реактивации, происходит создание экземпляра страницы, вызывается его конструктор, а затем вызывается перегруженный метод OnNavigatedTo этой страницы, если они присутствуют. Незадолго до перехода к другой странице, выхода или дезактивации вызывается метод OnNavigatedFrom. Экземпляры страницы используются повторно, только если пользователь переходит обратно на посещенные ранее страницы и приложение не было дезактивировано после этого посещения. В этом случае приложение вызывает методы OnNavigatedTo и OnNavigatedFrom, как и раньше, но без вызова конструктора перед этим.
На следующем изображении показан общий жизненный цикл приложения и страницы.

Обычно вы будете использовать события Launching, Activated, Closing и Deactivated для инициализации и поддержки состояния приложения. Однако, когда эти события происходят, телефон все еще находится в процессе загрузки или выгрузки приложения, потенциально вызывая значительные задержки. Чтобы избежать увеличения этих задержек, вы всегда должны избегать трудоемких операций в обработчиках для этих событий.
Обычно вы будете использовать перегруженные методы OnNavigatedTo и OnNavigatedFrom страницы для инициализации состояния страницы и выполнения или запуска трудоёмких операций, таких, как загрузка и сохранение данных. Когда метод OnNavigatedTo вызывается, приложение и страницы уже закончили загрузку и доступны для использования. Когда метод OnNavigatedFrom вызывается, приложение и страницы еще не начали выгружаться.
Сертификационное требование:
Ваше приложение должно отрисовать свой первый экран в течение 5 секунд после запуска и начать реагировать на действия пользователя в течение 20 секунд.
Для удовлетворения первого требования, вы можете отображать заставку. Для удовлетворения второго требования, вы можете загружать данные только тогда, когда это необходимо, и запускать трудоёмкие операции асинхронно, возможно, с использованием BackgroundWorker. Однако, даже если вы используете фоновый поток, вы должны запускать его в перегруженном методе OnNavigatedTo, а не в обработчиках событий Launching или Activated, чтобы избежать увеличения времени запуска.
Сертификационное требование:
Когда приложение выгружается, оно также должно завершить все операции в течение 10 секунд по запросу на закрытие или дезактивацию, в противном случае будет выброшено исключение и приложение будет прервано. Для удовлетворения этого требования вы должны рассмотреть сохранение данных, как только они становятся доступны, или постепенное сохранение, если имеются большие объёмы данных.
Следующая часть

