Pull to refresh

Создание приложения для Windows Phone 7 от начала до конца. Часть 13. Восстановление приложения после дезактивации

Reading time7 min
Views3.8K
Original author: Microsoft Developer Guidance team
Предыдущая часть

Когда пользователь покидает ваше приложения, оно дезактивируется. Если пользователь использует кнопку «Назад», чтобы вернуться к вашему приложению, вам необходимо восстановить приложение в соответствующее состояние.

В этой части вы узнаете:
  • Что такое tombstoning.
  • Как восстановить приложения после того, как оно было дезактивировано.
  • Когда выполнять другие действия в вашем приложении.

Обзор tombstoning


Ваше приложение может быть прервано и дезактивировано в любой момент, как правило, это происходит, когда пользователь переходит к другому приложению с помощью кнопки «Start». Когда это происходит, ваше приложение должно сохранить свое состояние так, чтобы оно могло быть восстановлено в случае возврата к нему. Однако, изолированное хранилище является слишком медленным для краткосрочного хранения данных о состоянии. Вместо этого, вы кэшируете данные, используя хранящиеся в памяти словари состоянии для того, чтобы быстро сохранить и загрузить данные.

Когда приложение дезактивируется, его процесс может быть остановлен с использованием процедуры, называемой tombstoning (tombstone — надгробная плита), которая сохранит записи приложения в памяти и свяжет их с вашими кэшированными данными о состоянии. Если пользователь переходит обратно в ваше приложение, операционная система перезапускает процесс приложения и передает ему обратно данные о состоянии.

Совет:
Когда работа приложения прерывается, а затем возобновляется, пользователи ожидают продолжения работы с того места, где она была прервана. По этой причине, вы всегда должны реализовывать поддержку tombstoning для любой страницы, которая может изменять свое состояние. Это относится к изменениям состояния настолько сложным, как обновление введённых пользователем данных, или настолько простым, как изменение текущего выделения в списке. Отсутствие поддержки tombstoning может привести к ухудшению юзабилити в лучшем случае и совершенно неожиданному поведению в худшем случае.

Сертификационное требование:
Ваше приложение не должно задерживать или препятствовать возможности пользователю совершить вызов, ответить на входящий вызов или завершить вызов.

Реализация поддержки tombstoning


Для того, чтобы использовать временный кэш, который сохраняется в течение tombstoning, выполните следующие действия:
  • Поместите данные о состоянии уровня приложения в свойство PhoneApplicationService.State в событии Deactivated и извлеките данные в обработчике события Activated.
  • Поместите данные о состоянии уровня страницы в свойство PhoneApplicationPage.State для каждой страницы в перегрузке метода OnNavigatedFrom и извлеките данные в перегрузке метода OnNavigatedTo.
Эти два свойства State представляют собой словари, в которых вы можете хранить пары вида значение/ключ, где значениями могут являться значения примитивных типов или сериализуемые объекты. Обратите внимание, что нет никакой гарантии, что дезактивированное приложение когда-либо будет повторно активировано, так что вы не должны использовать эти словари для хранения тех данных приложения или пользователя, которые должны быть сохранены. Для длительного хранения используйте изолированное хранилище.

Совет по улучшению производительности:
Используйте словари состояний для восстановления состояния. Избегайте восстановления состояния из изолированного хранилища или из Интернета.

Приложение Fuel Tracker сохраняет временные состояния уровня страницы в процессе tombstoning, но не имеет данных о состоянии уровня приложений для сохранения. Каждая страница сохраняет данные о состоянии с своё свойство PhoneApplicationPage.State. Например, класс FillupPage содержит объект Fillup, привязанный к некоторым текстовым полям. Этот объект сохраняется на длительное хранение, только когда пользователь нажимает кнопку «Save». Однако, во время tombstoning страница помещает объект в словарь State (состояние) страницы наряду со значением, указывающим, вносил ли пользователь изменения в него, как показано в следующем фрагменте кода. (Реализации кнопки «Save» будет описана в части «Валидация вводимых данных».)
  1. private const string CURRENT_FILLUP_KEY = "CurrentFillup";
  2. private const string HAS_UNSAVED_CHANGES_KEY = "HasUnsavedChanges";
  3. private Fillup currentFillup;
  4. private bool hasUnsavedChanges;
  5.  
  6. protected override void OnNavigatedFrom(NavigationEventArgs e)
  7. {
  8.     base.OnNavigatedFrom(e);
  9.     if (cacheChanges)
  10.     {
  11.         CommitTextBoxes();
  12.         this.State[CURRENT_FILLUP_KEY] = currentFillup;
  13.         this.State[HAS_UNSAVED_CHANGES_KEY] = hasUnsavedChanges;
  14.     }
  15. }
  16.  
  17. protected override void OnNavigatedTo(NavigationEventArgs e)
  18. {
  19.     base.OnNavigatedTo(e);
  20.  
  21.     CarHeader.DataContext = CarDataStore.Car;
  22.  
  23.     DataContext = currentFillup =
  24.         State.ContainsKey(CURRENT_FILLUP_KEY) ?
  25.         (Fillup)this.State[CURRENT_FILLUP_KEY] :
  26.         new Fillup() { Date = DateTime.Now };
  27.  
  28.     hasUnsavedChanges = State.ContainsKey(HAS_UNSAVED_CHANGES_KEY) ?
  29.         (bool)State[HAS_UNSAVED_CHANGES_KEY] : false;
  30. }
* 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, как и раньше, но без вызова конструктора перед этим.

На следующем изображении показан общий жизненный цикл приложения и страницы.

image

Обычно вы будете использовать события Launching, Activated, Closing и Deactivated для инициализации и поддержки состояния приложения. Однако, когда эти события происходят, телефон все еще находится в процессе загрузки или выгрузки приложения, потенциально вызывая значительные задержки. Чтобы избежать увеличения этих задержек, вы всегда должны избегать трудоемких операций в обработчиках для этих событий.

Обычно вы будете использовать перегруженные методы OnNavigatedTo и OnNavigatedFrom страницы для инициализации состояния страницы и выполнения или запуска трудоёмких операций, таких, как загрузка и сохранение данных. Когда метод OnNavigatedTo вызывается, приложение и страницы уже закончили загрузку и доступны для использования. Когда метод OnNavigatedFrom вызывается, приложение и страницы еще не начали выгружаться.

Сертификационное требование:
Ваше приложение должно отрисовать свой первый экран в течение 5 секунд после запуска и начать реагировать на действия пользователя в течение 20 секунд.

Для удовлетворения первого требования, вы можете отображать заставку. Для удовлетворения второго требования, вы можете загружать данные только тогда, когда это необходимо, и запускать трудоёмкие операции асинхронно, возможно, с использованием BackgroundWorker. Однако, даже если вы используете фоновый поток, вы должны запускать его в перегруженном методе OnNavigatedTo, а не в обработчиках событий Launching или Activated, чтобы избежать увеличения времени запуска.

Сертификационное требование:
Когда приложение выгружается, оно также должно завершить все операции в течение 10 секунд по запросу на закрытие или дезактивацию, в противном случае будет выброшено исключение и приложение будет прервано. Для удовлетворения этого требования вы должны рассмотреть сохранение данных, как только они становятся доступны, или постепенное сохранение, если имеются большие объёмы данных.

Следующая часть
Tags:
Hubs:
+1
Comments0

Articles