Внутренняя организация приложений под Android: архитектура и основные компоненты


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

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

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

Основные компоненты Android-приложений

Активности (Activities). Активность - это видимая часть приложения (экран, окно, форма), отвечает за отображение графического интерфейса пользователя. При этом приложение может иметь несколько активностей, например, в приложении, предназначенном для работы с электронной почтой, одна активность может использоваться для отображения списка новых писем, другая активность - для написания, и еще одна - для чтения писем. Несмотря на то, что для пользователя приложение представляется единым целым, все активности приложения не зависят друг от друга. В связи с этим любая из этих активностей может быть запущена из другого приложения, имеющего доступ к активностям данного приложения. Например, приложение камеры может запустить активность, создающую новые письма, чтобы отправить только что сделанную фотографию адресату, указанному пользователем.


Сервисы (Services). Сервис - компонент, который работает в фоновом режиме, выполняет длительные по времени операции или работу для удаленных процессов. Сервис не предоставляет пользовательского интерфейса. Например, сервис может проигрывать музыку в фоновом режиме, пока пользователь использует другое приложение, может загружать данные из сети, не блокируя взаимодействие пользователя с активностью. Сервис может быть запущен другим компонентом и после этого работать самостоятельно, а может остаться связанным с этим компонентом и взаимодействовать с ним.

Контент-провайдеры (Content providers). Контент-провайдер управляет распределенным множеством данных приложения. Данные могут храниться в файловой системе, в базе данных SQLite, в сети, в любом другом доступном для приложения месте. Контент-провайдер позволяет другим приложениям при наличии у них соответствующих прав делать запросы или даже менять данные. Например, в системе Android есть контент-провайдер, который управляет информацией о контактах пользователя. В связи с этим, любое приложение с соответствующими правами может сделать запрос на чтение и запись информации какого-либо контакта. Контент-провайдер может быть также полезен для чтения и записи приватных данных приложения, не предназначенных для доступа извне.

Приемники широковещательных сообщений (Broadcast Receivers). Приемник - компонент, который реагирует на широковещательные извещения. Большинство таких извещений порождаются системой, например, извещение о том, что экран отключился или низкий заряд батареи. Приложения также могут инициировать широковещание, например, разослать другим приложениям сообщение о том, что некоторые данные загружены и доступны для использования. Хотя приемники не отображают пользовательского интерфейса, они могут создавать уведомление на панели состояний, чтобы предупредить пользователя о появлении сообщения. Такой приемник служит проводником к другим компонентам и предназначен для выполнения небольшого объема работ, например, он может запустить соответствующий событию сервис.

Все рассмотренные компоненты являются наследниками классов, определенных в Android SDK.

Иерархия основных классов Android SDK, с которыми обычно имеет дело разработчик. На самом деле классов намного больше, желтым цветом выделены классы, с которыми разработчик работает непосредственно, наследует от них свои классы. Остальные классы не менее важны, но они реже используются напрямую.

View

Класс View является основным строительным блоком для компонентов пользовательского интерфейса (UI), он определяет прямоугольную область экрана и отвечает за прорисовку и обработку событий. Является базовым классом для виджетов (GUI widgets), которые используются для создания интерактивных компонентов пользовательского интерфейса: кнопок, текстовых полей и т. д. А также является базовым классом для класса ViewGroup, который является невидимым контейнером для других контейнеров и виджетов, определяет свойства расположения компонентов пользовательского интерфейса. Интерфейс Android-приложения представляет собой иерархию UI компонентов, можно описать эту иерархию программно, но более простым и эффективным способом задать расположение элементов интерфейса является XML файл, который предоставляет удобную для восприятия структуру компоновки (layout file). Во время исполнения XML файл автоматически превращается в дерево соответствующих объектов. Подробнее о классе View, свойствах и методах.


Intent

Объекты-экземпляры класса Intent используются для передачи сообщений между основными компонентами приложений. Известно, что три из четырех основных компонентов: активности, сервисы и приемники широковещательных сообщений, могут быть активированы с помощью сообщений, которые называются намерениями. Такие сообщения являются инструментом позднего связывания компонентов одного или нескольких приложений. Экземпляр класса Intent представляет собой структуру данных, содержащую описание операции, которая должна быть выполнена, и обычно используется для запуска активности или сервиса. В случае с приемниками широковещательных сообщений объект Intent содержит описание события, которое произошло или было объявлено.

Для каждого типа компонентов существуют свои механизмы передачи намерений.
  • Чтобы запустить активность или вызвать у работающей активности новое действие, необходимо передать объект-намерение в метод Context.startActivity() или Activity.startActivityForResult().
  • Чтобы запустить сервис или доставить новые инструкции работающему сервису, необходимо передать объект-намерение в метод Context.startService(). Также объект-намерение может быть передан в метод Context.bindService(), чтобы связать между собой вызывающий компонент и сервис.
  • Чтобы доставить объект-намерение всем заинтересованным приемникам широковещательных сообщений, необходимо передать его в любой из широковещательных методов: Context.sendOrderedBroadcast(), Context.sendStickyBroadcast(), Context.sendBroadcast().

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

Передача намерений (Intent)

На рисунке выше можно увидеть как происходит передача намерений (Intent), в данном случае одна активность запускает другую. Активность А создает намерение (Intent) с описанием действия и передает его в метод startActivity(). Система Android проверяет все приложения на совпадение с намерением, когда совпадение найдено, система запускает соответствующую активность, для чего вызывает метод onCreate() и передает в него объект-намерение Intent.

Подробнее о классе Intent:

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