В предыдущем выпуске этой серии статей о том, как разрабатывать приложение для Windows Phone с нуля, мы использовали Инструмент изолированного хранилища, чтобы взглянуть на содержимое ApplicationSettings , хранящееся в IsolatedStorage на устройстве или эмуляторе. На этот раз мы продолжаем работать с настройками нашего приложения, потому что мы поговорим о быстром переключении приложений и Tombstoning .
Как вы, наверное, знаете, только одно приложение может быть запущено на переднем плане на Windows Phone. Это приложение может использовать столько ресурсов, сколько ему нужно, и должно быть максимально быстрым, чтобы дать конечным пользователям отличный опыт. Как правило, пользователи часто переключаются между приложениями. Они могут даже не думать о разных приложениях, потому что они, скорее всего, очень ориентированы на задачи. Чтобы предоставить конечным пользователям лучший опыт, наши приложения разделяют ответственность с другими приложениями и с операционной системой.
Если наше приложение в настоящее время выполняется на переднем плане, есть две важные причины, по которым наше приложение должно прекратить работу на переднем плане:
- Пользователь закрывает наше приложение, нажимая клавишу «Назад» на телефоне, пока весь задний стек страниц нашего приложения не станет пустым.
- Наше приложение прервано, потому что произошло какое-то событие.
Первая ситуация проста. Когда наше приложение закрывается, мы несем ответственность за сохранение информации, которую мы хотим сохранить до следующего запуска нашего приложения. Это то, что мы сделали для EvenTiles в части 5 серии, используя методы Application_Launching и Application_Closing , которые определены в файле App.xaml.cs.
ПРИМЕЧАНИЕ . Описание «Быстрого переключения приложений и захоронения» в этой статье действительно для Windows Phone Mango, но не для предыдущих версий операционной системы.
На следующем рисунке показано, как наше приложение работает с течением времени. Пользователь перешел на страницу настроек на EvenTiles, изменил строковое значение и решил использовать ключ запуска на телефоне, чтобы запустить другое приложение. Через некоторое время пользователь возвращается в наше приложение, нажимая клавишу «Назад», пока наша страница настроек снова не станет видимой.
Для пользователя это очень удобно, потому что когда они возвращаются к нашему приложению, оно отображается точно так же, как и когда они переносили наше приложение в фоновый режим. Операционная система просто хранит наше приложение в памяти. Существуют некоторые ограничения в отношении приложений, использующих определенные ресурсы, такие как камера. Чтобы наша история была скудной и значимой, мы ее опускаем. Когда пользователь запускает много приложений (таким образом, помещая все больше приложений в фоновый режим), в какой-то момент объем доступной памяти становится настолько низким, что другое приложение больше не может быть запущено. В этой ситуации операционная система решает удалить самое старое приложение в фоновом режиме из памяти, сохраняя только минимальную информацию о состоянии для этого приложения. В этой ситуации приложение, которое было только что удалено из памяти, называетсяЗахороненных . Чтобы восстановить наше приложение от захоронения, нам нужно не только перезагрузить настройки приложения (как мы это делали в событии Application_Launching), но, скорее всего, нам также необходимо восстановить дополнительные данные. Операционная система «запоминает» страницу в нашем приложении, которую пользователь видел, когда мы были захоронены. Мы несем ответственность за восстановление данных, введенных пользователем на этой странице (например, содержимого текстового поля).
Когда наше приложение отправляется в фоновом режиме, происходит несколько вещей. На странице, которая видна в данный момент, происходит событие OnNavigatedFrom . Также будет вызван метод Application_Deactivation в файле App.xaml.cs. Когда приложение переключается в фоновый режим, с ним могут происходить три вещи:
- Приложение снова станет основным приложением, не войдя в состояние захоронения. В этой ситуации приложение может извлечь выгоду из быстрого переключения приложений.
- Приложение было захоронено, но через некоторое время оно станет основным приложением. В этой ситуации приложение должно восстановить больше информации о состоянии.
- Пользователь снова запускает приложение, щелкая его значок или плитку на начальном экране. В этой ситуации предыдущий экземпляр приложения удаляется, и пользователь должен увидеть приложение в его начальном состоянии.
При отладке приложения в Visual Studio поведение по умолчанию, когда приложение перемещается в фоновый режим, заключается в том, что оно остается в памяти. Однако, изменив одно из свойств проекта (как показано на снимке экрана слева), вы можете принудительно заставить приложение стать захороненным, независимо от объема свободной памяти на устройстве (эмуляторе). Таким образом, мы, как разработчики, имеем возможность тестировать наши приложения в любом состоянии, в которое они входят, когда переходят в фоновый режим. Вы должны убедиться, что вы тестируете сценарий захоронения для своего приложения. Например, если EvenTiles с его текущей функциональностью протестирован на надгробие, он потерпит крах. В настоящее время это связано с тем, как данные инициализируются. В EvenTiles у нас есть строковое свойство, определенное в App.xaml.cs, который позже будет использоваться для записи информации на обратную сторону вторичной плитки. Страница настроек уже использует это свойство. Однако мы инициализируем это свойство с именемActualBackSecContent, когда приложение запускается в методе Application_Launching.
Активация и прекращение
// Code to execute when the application is launching (eg, from Start) // This code will not execute when the application is reactivated private void Application_Launching(object sender, LaunchingEventArgs e) { if (!appSettings.Contains(keyActSecBackContent)) { appSettings[keyActSecBackContent] = DefaultSecBackContent; } ActualSecBackContent = (string)appSettings[keyActSecBackContent]; } // Code to execute when the application is activated (brought to foreground) // This code will not execute when the application is first launched private void Application_Activated(object sender, ActivatedEventArgs e) { } // Code to execute when the application is deactivated (sent to background) // This code will not execute when the application is closing private void Application_Deactivated(object sender, DeactivatedEventArgs e) { } // Code to execute when the application is closing (eg, user hit Back) // This code will not execute when the application is deactivated private void Application_Closing(object sender, ClosingEventArgs e) { appSettings[keyActSecBackContent] = ActualSecBackContent; }
Несмотря на то, что наше приложение удаляется из памяти, когда оно захоронено, если пользователь перемещается по заднему стеку с помощью клавиши возврата на телефоне, в конечном итоге он вернется на страницу нашего приложения. Чтобы это произошло в случае, если наше приложение было захоронено, его необходимо снова загрузить в память, чтобы оно стало активным. В этой ситуации минимальная информация о состоянии сохранялась операционной системой (например, какая страница была последней страницей, которую пользователь увидел, когда наше приложение было захоронено). Вернувшись из надгробия, мы вернемся к этой странице, но, поскольку приложение должно быть полностью запущено, классы должны быть заново созданы, и для этого будет выполнен код в конструкторах этих классов. Чтобы различать запуск новой копии приложения или возврат из фона,Application_Launching (свежий перезапуск) или Application_Activation (захоронение или быстрое переключение приложений) вызывается в нашем файле App.xaml.cs. Если наше приложение все еще находится в памяти, проблем нет, в конце концов, свойство ActualSecBackContent по- прежнему сохраняет свое значение. Если мы возвращаемся из сложного положения, у нас есть проблема, так как Application_Activation будет вызываться вместо Application_Launching . Вот почему возникло исключение, показанное в приведенном выше снимке экрана.
Вы можете подумать, что эту проблему легко решить, инициализируя свойство ActualSecBackContent в конструкторе нашего класса App, но это будет означать, что мы не выиграем от быстрого переключения приложений (ситуация, когда наше приложение остается в памяти, даже если оно на заднем плане). Лучшее решение — использовать событие Application_Activation следующим образом:
Переключение между BG и FG
// Code to execute when the application is activated (brought to foreground) // This code will not execute when the application is first launched private void Application_Activated(object sender, ActivatedEventArgs e) { if (!e.IsApplicationInstancePreserved) { // The application was not preserved in memory, so we were tombstoned // Only in this case we need to re-initialize ActualSecBackContent ActualSecBackContent = (string)appSettings[keyActSecBackContent]; } } // Code to execute when the application is deactivated (sent to background) // This code will not execute when the application is closing private void Application_Deactivated(object sender, DeactivatedEventArgs e) { appSettings[keyActSecBackContent] = ActualSecBackContent; }
Если приложение становится приложением переднего плана, мы проверяем, были ли мы все еще доступны в памяти. Если это так ( e.IsApplicationInstancePreserved == true ), мы ничего не делаем, в противном случае мы просто инициализируем свойство ActualSecBackContent. Больше ничего не нужно делать, потому что мы знаем, что значение с этим конкретным ключом настроек уже доступно, поскольку приложение было запущено за некоторое время до Application_Activation.назывался. Если приложение перемещено в фоновый режим, вы должны убедиться, что все сохранено таким образом, что вы предполагаете, что ваше приложение никогда не вернется в фоновый режим. В конце концов, приложение может оставаться в памяти, оно может быть захоронено, но есть также возможность, что пользователь запускает новый экземпляр приложения из меню «Пуск». В последнем случае существующий экземпляр приложения в фоновом режиме будет удален операционной системой.
ПРИМЕЧАНИЕ. Если вы обновляете существующее приложение для Mango, по крайней мере (после преобразования вашего проекта в Visual Studio) вам нужно только извлечь сохраненные данные в методе Application_Activation, если e.IsApplicationInstancePreserved имеет значение false . Таким образом, ваше приложение сразу же выиграет от быстрого переключения приложений.
На следующем видео показаны действия, которые мы предприняли, чтобы предотвратить сбой приложения EvenTiles после повторной активации из захороненного состояния:
С изменениями, которые были описаны до сих пор, добавлено в наше приложение, оно больше не падает, если мы возвращаемся из состояния захоронения. Однако есть и другие вещи, которые необходимо учитывать при возврате приложения из фона на передний план. В следующем Эпизоде EvenTiles мы рассмотрим восстановление Фокуса на элементе управления вводом при возвращении из фона.
Если вы хотите, чтобы EvenTiles уже работали на вашем Windows Phone, вы можете установить последнюю версию Marketplace. Помните, что это приложение не должно быть чрезвычайно полезным, хотя оно содержит аналогичные функции, которые есть у «серьезных» приложений. Все функции, которые вы можете найти в выпущенной версии EvenTiles, будут описаны в следующих выпусках этой серии блогов вместе со всем исходным кодом. Просто получите бесплатную копию EvenTiles в Marketplace по следующему адресу : http://www.windowsphone.com/en-US/search?q=EvenTiles (или найдите на телефоне EvenTiles в приложении Marketplace).
Источник: http://mstruys.com/2011/12/12/eventiles-from-start-to-finishpart-7/