Реализация быстрого переключения приложений
Основные теоретические сведения
В Windows Phone одновременно может быть активным только одно приложение. Когда приложение перестаёт быть активным, операционная система переводит его в состояние "бездействует". Если памяти устройства недостаточно для работы активного приложения, операционная система начинает завершать бездействующие приложения. При этом, последними будет завершены приложения, которые запускались недавно.
Платформа Windows Phone предоставляет разработчику события, методы и объекты, которые он может использовать для необходимых действий на каждом жизненном цикле приложения.
Приложение позволяет разработчику обработать события Launching, Closing, Activated и Deactivated. Поскольку пользователь покидает какую-то страницу или переходит на какую-то страницу приложения, с этими событиями связаны два доступных для переопределения метода страниц приложения: OnNavigatedTo и OnNavogatedFrom.
Для того, чтобы понять, как приложение и система взаимодействуют и какие возможности есть у разработчика, рассмотрим несколько сценариев жизненных циклов приложения.
Пользователь запускает приложение со стартовой страницы телефона или списка приложений, работает с приложением, затем нажимает кнопку Назад телефона, находясь на стартовой странице приложения:
- Приложение запускается, вызывается событие Launching.
- Загружается стартовая страница приложения, вызывается её метод OnNavigatedTo.
- Приложение работает.
- Пользователь выходит из приложения, нажимая кнопку Назад, находясь на стартовой странице приложения.
- Вызывается метод OnNavogatedFrom стартовой страницы приложения.
- Вызывается событие Closing приложения.
Пользователь запускает приложение со стартовой страницы телефона или списка приложений, работает с приложением, затем нажимает кнопку перехода к стартовой странице телефона, находясь на любой странице приложения, а потом быстро возвращается обратно (операционная система не завершает приложение), используя длинное нажатие кнопки Назад и выбирая страницу приложения, с которой он ушёл.
- Приложение запускается, вызывается событие Launching.
- Загружается стартовая страница приложения, вызывается её метод OnNavigatedTo.
- Приложение работает.
- Пользователь выходит из приложения, нажимая кнопку Назад, находясь на стартовой странице приложения.
- Вызывается метод OnNavogatedFrom стартовой страницы приложения.
- Вызывается событие Deactivated приложения.
- Приложение переходит в состояние "бездействует".
- Пользователь не интенсивно пользуется телефоном, поэтому выгрузки приложения из спящего состояния не происходит.
- Пользователь возвращается в приложение, используя "длинное нажатие" кнопки Назад и выбирая страницу приложения, с которой он ушёл.
- Вызывается событие Activated приложения.
- Загружается страница приложения, с которой ушёл пользователь, и вызывается её метод OnNavigatedTo.
- Приложение работает.
Если операционной системе потребуется больше памяти, когда приложение находится в памяти в состоянии "бездействует", то приложение завершит свою работу, но сохранит состояние стека навигации, а также состояние словарей состояния на уровне приложения и на уровне страницы, и перейдёт в состояние "выгружено". Обратите внимание, что выход из состояния "выгружено" не отличается от выхода из состояния "бездействует", но при этом, поскольку приложение будет выгружено из памяти, необходимо позаботиться о сохранении данных для восстановления состояния приложения. Узнать об этом разработчик может, проверив свойство IsApplicationInstancePreserved у ActivatedEventArgs: если значение свойства равно true, приложение восстанавливается из состояния "бездействует", если false — то из состояния выгружено.
Одновременно система сохраняет состояние "выгружено" только для пяти приложений. Если пользователь не возвращается к приложению, данные удаляются, и приложение будет запускаться с событием Launching.
Давайте теперь на практике попробуем разобраться с сохранением состояния приложения.
Создадим новое приложение на базе стандартного шаблона Приложение Windows Phone и назовём приложение ApplicationStateExample.
Исправьте код XAML страницы приложения на следующий:
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="STATE SAVER" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="message log" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <TextBox Name="Message" Height="200" TextWrapping="Wrap" / > <Button Name="Log" Height="80" Content="Log" / > </StackPanel> </Grid>
Запустите приложение. Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удерживайте кнопку Назад — отобразится список доступных приложений. Выберите наше приложение. Обратите внимание, что состояние страницы сохранилось, так как приложение было в состоянии "бездействует".
Завершите работу приложения, перейдите в свойства проекта и установите флажок Отметить как удаленный в результате деактивации во время:
Запустите приложение. Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удерживайте кнопку Назад — отобразится список доступных приложений. Выберите наше приложение. Обратите внимание, что состояние страницы не сохранилось, так как приложение было выгружено из памяти, и состояние страницы и приложения было утеряно.
Добавим в код страницы MainPage.xaml.cs функции OnNavigatedFrom и OnNavigatedTo, сохранив текст из поля ввода в словарь состояний:
protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); this.State.Add("text", Message.Text); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (this.State.ContainsKey("text")) { Message.Text = (string)this.State["text"]; } }
Запустите приложение. Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удерживайте кнопку Назад — отобразится список доступных приложений. Выберите наше приложение. Обратите внимание, что состояние страницы сохранилось, несмотря на то, что приложение было выгружено из памяти, так как мы сохранили состояние страницы в специальном словаре для сохранения состояния страницы.
Это не совсем правильное поведение кода, поскольку в случае, если приложение восстанавливается из состояния "бездействует", не нужно изменять состояние страниц.
Добавим логическую переменную, чтобы определить, вызвался ли конструктор, и модифицируем код соответствующим образом:
bool isNewlyCreatedPage = false; // Конструктор public MainPage() { InitializeComponent(); isNewlyCreatedPage = true; } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (this.State.ContainsKey("text") && isNewlyCreatedPage) { Message.Text = (string)this.State["text"]; } isNewlyCreatedPage = false; }
Запустите приложение и проверьте, как оно работает.
Снимите флажок настройки отладки Отметить как удаленный в результате деактивации во время и проверьте, что приложение не восстанавливает состояние в случае выхода из состояния "бездействует".
Добавим в приложение код, чтобы попробовать сохранить состояние приложения.
Добавим элемент TextBlock и обработчик Click в XAML код страницы:
<StackPanel> <TextBox Name="Message" Height="200" TextWrapping="Wrap" /> <Button Name="Log" Height="80" Content="Log" Click="Log_Click" /> <TextBlock Name="AppState" Height="80" /> </StackPanel>
В файл App.xaml.cs добавим публичное поле AppState:
public string AppState = "";
Модифицируем код файла MainPage.xaml.cs, чтобы при нажатии на кнопку сообщение из TextBox записывалось в AppState и отображалось в TextBlock, а при восстановлении приложения AppState отображалось в TextBlock:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); if (this.State.ContainsKey("text") && isNewlyCreatedPage) { Message.Text = (string)this.State["text"]; App myApp = App.Current as App; AppState.Text = myApp.AppState; } isNewlyCreatedPage = false; } private void Log_Click(object sender, RoutedEventArgs e) { AppState.Text = Message.Text; App myApp = App.Current as App; myApp.AppState = AppState.Text; }
Теперь необходимо добавить код сохранения/восстановления в App.xaml.cs:
// Код для выполнения при активации приложения (переводится в основной режим) // Этот код не будет выполняться при первом запуске приложения private void Application_Activated(object sender, ActivatedEventArgs e) { if (!e.IsApplicationInstancePreserved) { AppState = (string)PhoneApplicationService.Current.State["appState"]; } } // Код для выполнения при деактивации приложения (переводится в фоновый режим) // Этот код не будет выполняться при закрытии приложения private void Application_Deactivated(object sender, DeactivatedEventArgs e) { PhoneApplicationService.Current.State.Add("appState", AppState); }
Перейдите в настройки отладки и установите флажок Отметить как удаленный в результате деактивации во время, а затем запустите приложение и проверьте, что состояние приложения сохраняется.
Обратите внимание, что когда приложение вызывает задачи выбора и запуска, также возникает события Deactivated.
Дополнительные материалы
Windows Phone 7.5 Training Kit: Labs\ApplicationLifecycle\ApplicationLifecycle.html\html\ DocSet_default.html.
Сайт MSDN: http://msdn.microsoft.com/ru-ru/library/ff769557.
Задание к работе
- Откройте в Visual Studio созданный в одной из предыдущих работ проект программы для Windows Phone.
- Добавьте необходимый код для сохранения состояния программы при её деактивации и восстановления состояния программы при возобновлении её работы.
- Запустите программу и проверьте правильность её работы при возобновлении работы из состояний "бездействует" и "выгружено".
- Составьте отчёт о проделанной работе. Включите в отчёт необходимые листинги программы.