Главная » Программирование игр под Android » Жизненный цикл активности – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

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

В теории

Активность может находиться в одном из трех состояний.

Работает. В этом состоянии активность является текущей, занимает экран и напрямую взаимодействует с пользователем.

Приостановлена. Состояние наступает, когда активность все еще видна на экране, но частично закрыта либо другой прозрачной активностью, либо диалогом, либо экран заблокирован. Приостановленная активность может быть уничтожена системой в любой момент (например, при нехватке памяти). Обратите внимание – экземпляр приостановленной активности не уничтожается; он продолжает храниться в куче VM, ожидая возвращения в работающее состояние. Остановлена. Состояние наступает, когда активность полностью закрыта другой активностью и поэтому больше не видна на экране. Например, наша активность AndroidBasicsStarter перейдет в данное состояние, если мы запустим одну из тестовых активностей. Кроме того, переход в данное состояние наступает при нажатии пользователем кнопки Ноте (Домой) для перехода на домашний экран ОС. Система также может уничтожить остановленную активность и выгрузить ее из памяти при ее нехватке.

Как видите, и в приостановленном, и в остановленном состояниях система Android может уничтожить активность в любой момент. Это может происходить вежливо, с предварительным информированием активности (вызовом метода finishedC), или грубо, молчаливым уничтожением процесса.

Активность может быть возвращена в работающее состояние из режимов паузы или остановки. Снова замечу – активность в любом состоянии является одним и тем же Java-экземпляром в памяти, поэтому все ее содержимое остается в том же состоянии, что и перед остановкой или приостановкой.

У активности есть несколько защищенных методов, которые мы можем переопределить для получения информации об изменениях состояния.

Activity .onCreate – метод вызывается при первом запуске активности. В нем мы устанавливаем компоненты интерфейса и обращаемся к системе ввода. Этот метод вызывается всего один раз в течение жизненного цикла активности.

Activity .onRestart – метод вызывается при возвращении активности из остановленного состояния. Ему должен предшествовать вызов метода onStop.

Acti vity .onStartC – метод вызывается после метода onCreate или когда активность возвращается из остановленного состояния. Во втором случае ему предшествует вызов метода onRestart.

Acti vity .onResume – метод вызывается после вывода метода onStartO или когда активность возвращается из приостановленного состояния (например, при разблокировке экрана).

Activity. onPauseO – метод вызывается при переходе активности в приостанов-х ленное состояние. Это может оказаться последним полученным нами оповещением, поскольку ОС может решить закрыть наше приложение без уведомления. Поэтому в этом методе нам необходимо сохранить все важные для нас параметры приложения.

Acti vi ty. onStop – метод вызывается при переходе активности в режим остановки. Ему предшествует вызов метода onPause – перед переходом активности в остановленное состояние она всегда сначала проходит режим паузы. Как и в случае с onPause, это может быть последний момент, когда мы получаем информацию от приложения перед его закрытием операционной системой. Здесь мы также можем сохранить текущее состояние. Однако система может решить не вызывать этот метод и просто уничтожить активность. Поэтому, поскольку перед onStop и молчаливым закрытием приложения всегда вызывается onPause, сохранение важной для нас информации лучше всего поручить методу onPause.

Acti vi ty. onDestroy  – метод вызывается в конце жизненного цикла активности, когда она окончательно уничтожается. Это последняя точка, в которой мы можем получить и сохранить какие-то данные, которые хотим получить обратно при пересоздании нашей активности. Обратите внимание – этот метод может никогда не вызываться, если активность была уничтожена системой в неявном режиме после вызова onPauseC или onStopO.

Рисунок 4.3 иллюстрирует жизненный цикл активности и порядок вызова методов.

Рис. 4.3. Мощный и запутанный жизненный цикл активности

Итак, из теоретической части нам необходимо извлечь три важных урока.

Перед переходом нашей активности в работающее состояние всегда вызывается метод onResume вне зависимости от того, возвращаемся мы из приостановленного или остановленного состояния. Поэтому мы спокойно можем игнорировать методы onRestartO и onStartO. Нам не нужно заботиться о том, из какого состояния возвращается активность. В случае с нашими играми нам следует лишь знать, что сейчас активность запущена, для чего вполне достаточно сигнала от метода onRes ume .

Активность может быть уничтожена без оповещения после вызова метода onPauseC. Поэтому мы никогда не должны полагаться на обязательный вызов методов onStop или onDestroyC. Мы также знаем, что onPauseC всегда предшествует вызову onStop, поэтому мы вполне можем игнорировать методы onStopC и onDest гоу  – нам достаточно будет переопределить метод onPause . В нем мы можем обеспечить сохранение всей важной для нас информации (например, текущего уровня или лучших результатов), записав их на внешний носитель (карту памяти). После вызова onPauseC прием ставок заканчивается, и мы не будем знать, запустится ли наше приложение.

Мы знаем, что метод onDest гоу  может никогда не быть вызван, если система решит уничтожить активность после вызова методов onStop или onPause. Тем не менее нам было бы неплохо знать, готовится ли наша активность к уничтожению. Как же мы узнаем об этом, если onDest гоу  не будет вызван? Класс Activity включает в себя метод Activity, isFinishing, который мы можем вызывать в любое время, чтобы проверить, планируется ли уничтожение нашей активности. Нам гарантирован вызов по крайней мере метода onPause перед уничтожением активности. Все, что нам нужно, – вызвать is Finishing внутри метода onPauseC, чтобы понять, планирует ли система уничтожение активности после вызова onPauseC.

Все это несколько упрощает дело. Нам необходимо переопределить лишь следующие методы: onCreateC – создаем наше окно и визуализируемые компоненты интерфейса, а также получаем пользовательский ввод; onResumeС – стартуем (или возобновляем); onPauseC – ставим на паузу поток основного цикла и, если Activity. is Finishing возвращает true, сохраняем на диск важную информацию.

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

На практике

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

Создадим отдельный TextVi ew – компонент интерфейса для отображения в активности. Он нужен для вывода текста (мы уже использовали его неявно для демонстрации элементов списка в нашей стартовой активности). Каждый раз при переходе в новое состояние мы добавляем строку к элементу TextVi ew, который в результате сможет показать нам всю историю изменений состояний приложения.

Поскольку у нас не будет возможности показать событие разрушения нашей активности в TextVi ew (оно исчезнет с экрана слишком быстро), мы также отследим изменения состояний в LogCat. Это будет реализовано с помощью класса Log, предлагающего набор статических методов для добавления сообщений в LogCat.

Помните, что нам необходимо добавить тестовую активность в наше тестовое приложение. Во-первых, мы определяем ее в файле манифеста в виде элемента <acti vity>, являющегося дочерним по отношению к <appl i cati on>:

Далее мы добавляем новый Java-класс LifeCycleTest в пакет com.badlogic. androidgames. Наконец, нам необходимо добавить название этого класса в массив tests класса AndroidBasicsStarter, определенного нами ранее. Нам придется повторить все эти шаги для всех тестовых активностей, которые мы будем создавать далее. Для краткости я больше не буду о них упоминать. Заметьте также, что я не определил ориентацию экрана для активности LifeCycleTest. В данном примере она может быть как портретной, так и ландшафтной, в зависимости от расположения устройства. Это сделано для того, чтобы вы могли увидеть влияние изменения ориентации, на жизненный цикл активности (вообще это зависит от значения атрибута configChanges). Листинг 4.2 демонстрирует код активности.

Листинг 4.2. LifeCycleTest.Java, демонстрирующий жизненный цикл активности package com.badlogi с.androi dgames;

Быстро пробежимся по коду. Как и ожидалось, класс наследуется от Activity. В нем определены два члена – StringBuilder, хранящий все созданные нами сообщения, и TextView, который используется для отражения этих сообщений в активности.

Далее мы определяем маленький вспомогательный метод, записывающий текст в журнал LogCat, добавляющий текст в StringBuilder и обновляющий TextVi ew. Для вывода в LogCat используется статический метод Log.dO, в качестве первого аргумента принимающий тег, а в качестве второго – текст сообщения.

В методе onCreateC) мы, как всегда, вызываем сначала метод базового класса. Далее мы создаем объект TextVi ew и устанавливаем его в качестве просмотрщика содержимого для нашей активности. Этот элемент займет все пространство нашей активности. Наконец, мы записываем созданное сообщение в LogCat и обновляем значение текста в TextView с помощью ранее определенного метода 1 од.

Затем мы переопределяем метод onResumeС). Как и со всеми переопределяемыми методами активности, сначала вызываем метод базового класса. После этого все, что мы делаем, – вновь вызываем метод 1 од с текстом resumed в качестве аргумента.

Переопределенный метод onPauseC) выглядит очень похожим на onResumeO. Мы записываем в журнал строку paused (остановлено). Нам также необходимо знать, собирается ли система уничтожить активность после вызова onPauseC), поэтому мы вызываем метод Acti vity. i sFi ni shi ng. Если он возвращает значение true, мы также пишем об этом в журнал. Конечно, в этом случае мы не сможем увидеть обновленный текст в TextVi ew – активность будет уничтожена до того, как изменение отобразится на экране. Поэтому-то мы и выводим сообщения в журнал LogCat.

Запустите приложение и поиграйтесь немного с тестовой активностью. Вот последовательность действий, которую вы можете выполнить.

1. Запустить тестовую активность из стартовой активности.

2. Заблокировать экран.

3. Разблокировать экран.

4. Нажать кнопку Ноте (Домой) (которая вернет вас на стартовый экран ОС).

5. В экране Ноте (Стартовый экран) удерживать кнопку Ноте (Домой), пока на экране не появится список запущенных приложений. Выберите приложение Android Basics Start для его возобновления (это вернет вас на экран тестовой активности).

6. Нажать кнопку Назад (это вернет вас на стартовую активность).

Если система не решит уничтожить вашу активность без уведомления в любой момент, когда она находится в приостановленном состоянии, вы увидите на экране нечто, похожее на рис. 4.4 (если, конечно, еще не вышли из активности кнопкой Назад).

Рис. 4.4. Работающая активность LifeCycleTest

При запуске активности вызывается метод onCreate, далее следует onResume. При блокировке дисплея вызывается onPauseO, при разблокировке – onResumeO. Нажав кнопку Ноте (Домой), мы запускаем метод onPause. Возврат к активности вновь влечет за собой вызов onResume. Те же сообщения показаны в LogCat – вы можете увидеть их в представлении LogCat в Eclipse. На рис. 4.5 изображено все, что мы записали в LogCat при выполнении рассмотренной выше последовательности действий (плюс нажатие кнопки Назад).

Рис. 4.5. Вывод в LogCat активности LifeCycleTest

Как видите, нажатие кнопки Назад активизирует метод onPause. Он также уничтожает активность – проверка в onPause сообщает нам, что это последнее сообщение, которые мы увидим от активности.

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

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии