Северный (Арктический) федеральный университет им. М.В. Ломоносова
Опубликован: 10.04.2014 | Доступ: свободный | Студентов: 6837 / 1233 | Длительность: 14:18:00
Специальности: Программист
Лекция 2:

Виды приложений и их структура

3.4.1 Активности (Activities)

Активность - окно, несущее графический интерфейс пользователя. Окно активности обычно занимает весь экран устройства, однако вполне возможно создавать полупрозрачные или плавающие диалоговые окна. Мобильные приложения обычно являются многооконными, т. е. содержат несколько активностей, по одной на каждое окно. Одна из активностей определяется как "главная", и именно ее пользователь видит при первом запуске приложения.

Каждый экран приложения является наследником класса Activity. Для создания активности необходимо создать класс-наследник класса Activity напрямую или через любого его потомка. В этом классе необходимо реализовать все методы, вызываемые системой для управления жизненным циклом активности. Таких методов семь:

onCreate() - метод, вызываемый системой при создании активности. В реализации метода необходимо инициализировать основные компоненты активности и в большинстве случаев вызвать метод setContentView() для подключения соответствующего XML-файла компоновки (layout file). После метода onCreate() всегда вызывается метод onStart().
onRestart() - метод, вызываемый системой при необходимости запустить приостановленную активность. После этого метода всегда вызывается метод onStart().
onStart() - метод, вызываемый системой непосредственно перед тем, как активность станет видимой для пользователя. После этого метода вызывается onResume().
onResume() - метод, вызываемый системой непосредственно перед тем, как активность начнет взаимодействовать с пользователем. После этого метода всегда вызывается onPause().
onPause() - метод, вызываемый системой при потере активностью фокуса. В этом методе необходимо фиксировать все изменения, которые должны быть сохранены за пределами текущей сессии. После этого метода вызывается onResume(), если активность вернется на передний план, или onStop(), если активность будет скрыта от пользователя.
onStop() - метод, вызываемый системой, когда активность становится невидимой для пользователя. После этого метода вызывается либо onRestart(), если активность возвращается к взаимодействию с пользователем, либо onDestroy(), если активность уничтожается.
onDestroy() - метод, вызываемый системой перед уничтожением активности. Этот метод вызывается либо когда активность завершается, либо когда система уничтожает активность, чтобы освободить ресурсы. Можно различать эти два сценария с помощью метода isFinishing(). Это последний вызов, который может принять активность.
Жизненный цикл активности

Рис. 3.4. Жизненный цикл активности

(источник: http://developer.android.com/guide/components/activities.html).

При реализации вышеперечисленных методов первым делом всегда необходимо вызывать соответствующий метод предка.

Рассмотренные методы определяют жизненный цикл активности. На рис. 3.4 можно увидеть пути, по которым активность может переходить из одного состояния в другое. В прямоугольниках указаны методы, которые вызываются при смене состояний активности.

Фактически активность может существовать в одном из трех состояний:

  • Выполняется (running). Активность находится на переднем плане и удерживает фокус ввода. Если внимательно рассмотреть рис. 3.4 можно заметить, что в это состояние активность попадает после вызова метода onResume(). Пока активность находится в этом состоянии ее процесс не может быть уничтожен системой.
  • Приостановлена. Активность частично видима, однако фокус ввода потерян. В это состояние активность попадает после вызова метода onPause() ( рис. 3.4). В этом состоянии активность поддерживается в "боевой готовности", т.е. в любой момент может получить фокус ввода и стать активной. Однако в этом состоянии процесс активности может быть уничтожен системой, в случае экстремальной нехватки памяти.
  • Остановлена. Активность полностью невидима. В это состояние активность попадает после вызова метода onStop()( рис. 3.4). В этом состоянии активность может быть "вызвана к жизни", она сохраняет все состояния и необходимую для восстановления информацию, однако процесс активности может быть уничтожен, если память понадобится для других целей.

3.4.2 Сервисы (Services)

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

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

Для создания сервиса необходимо создать класс-наследник класса Service напрямую или через любого его потомка. При этом в реализации класса необходимо переопределить (т. е. написать свою реализацию) некоторые методы, управляющие ключевыми аспектами жизненного цикла сервиса и обеспечивающие механизм связывания компонентов с сервисом, в соответствующем случае. Рассмотрим наиболее важные методы требующие реализации при создании сервиса.

onStartCommand() - метод, вызываемый системой, когда некоторый компонент, например активность, вызывает метод startService(). В этом случае сервис запускается и может работать в фоновом режиме неопределенно долго, поэтому необходимо позаботиться об остановке сервиса, когда он выполнит свою работу. Для остановки сервиса используется метод stopSelf() в случае, когда сервис сам прекращает свою работу, или stopService() в случае, когда работу сервиса прекращает некоторый компонент. Нет необходимости писать реализацию метода onStartCommand(), если не предполагается самостоятельной работы сервиса (т. е. он будет работать только в связке с некоторыми компонентами).
onBind() - метод, вызываемый системой, когда некоторый компонент желает привязать к себе сервис и вызывает метод bindService(). Этот метод должен возвращать реализацию интерфейса IBinder, которая может быть использована компонентом-клиентом для взаимодействия с сервисом. Метод onBind() необходимо реализовать в любом случае, но, если не предполагается связывания сервиса с какими-либо компонентами, возвращаемое значение должно быть равным null.

Необходимо отметить, что сервис может быть запущен как самостоятельная единица, а впоследствии может быть привязан к некоторым компонентам. В этом случае в сервисе должны быть обязательно реализованы оба метода onStartCommand() и onBind().

onCreate() - метод, вызываемый системой, при первом обращении к сервису для выполнения первоначальных настроек. Этот метод вызывается до вызова методов onStartCommand() и/или onBind().
onDestroy() - метод, вызываемый системой, когда сервис либо выполнил все действия, для которых создавался, либо больше не связан ни с одним компонентом, т. е. его услуги больше не требуются. В реализации этого метода необходимо предусмотреть освобождение всех ресурсов, таких как потоки, зарегистрированные слушатели, приемники и т. д. Вызов этого метода является последними вызовом, который может получить сервис.

Жизненный цикл сервиса

Рис. 3.5. Жизненный цикл сервиса

(источник: http://developer.android.com/guide/components/services.html).

На рис. 3.5 показан жизненный цикл сервиса, левая диаграмма показывает жизненный цикл самостоятельного сервиса, правая - жизненный цикл сервиса, привязанного к некоторым компонентам. На рисунке хорошо видно, что жизненный цикл сервиса намного проще жизненного цикла активности. Однако для разработчика понимание того, как именно сервис создается, запускается и завершает свою работу, может оказаться даже более важным, т. к. сервис работает в фоновом режиме и пользователь может и не осознавать, что в некоторых случаях он имеет дело с работой сервисов.

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

Подробнее о создании, использовании и удалении сервисов:

Марат Нуриджанян
Марат Нуриджанян

Пример: Скачать среду можно с сайта для разработчиков Android (http://developer.android.com/sdk/index.html).

Там скачать можно только Android Studio

Владимир Каункин
Владимир Каункин

В самостоятельной работе 2 в примере решения задания некорректно загадывается число (в двух местах), выбирая случайное целое число из диапазона [0, 99] вместо [1, 100], как того требует условие. Кроме того, загадывание числа всё таки лучше вынести в отдельный метод, как мне кажется.