Android architecture components dependencies lifecycle

Android Architecture Components. Часть 2. Lifecycle

Как я уже упоминал в предыдущем материале, компонент Lifecycle призван упростить работу с жизненным циклом, а имено избежать калбеков с Activity/Fragment в наш компонент, который должен реагировать на события жизненого цикла. В этой статье, мы подробно разберем как он устроен и как с ним работать.

Сам компонент состоит из классов: Lifecycle, LifecycleActivity, LifecycleFragment, LifecycleService, ProcessLifecycleOwner, LifecycleRegistry. Интерфейсов: LifecycleOwner, LifecycleObserver, LifecycleRegistryOwner.

Lifecycle — класс, который хранит информацию про состояние жизненного цикла и разрешает другим объектам отслеживать его c помощью реализации LifecycleObserver. Состоит из методов: addObserver(LifecycleObserver), removeObserver(LifecycleObserver) и getCurrentState(). Как понятно из названий для добавления подписчика, удаления и соответственно получения текущего состояния.

Для описания состояния есть два enum. Первый Events — который обозначает изменение цикла и второй State — который описывает текущее состояние.

Events — повторяет стадии жизненного цикла и состоит из ON_CREATE, ON_RESUME, ON_START, ON_PAUSE, ON_STOP, ON_DESTROY, а также ON_ANY который информирует про изменения состояния без привязки к конкретному этапу. Отслеживание изменений цикла происходит с помощью пометки метода в обсервере аннотацией OnLifecycleEvent, которому как параметр передается интересуещее нас событие.

State — состоит из следующих констант: INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED. Для получения состояния используеться метод getCurrentState() из Lifecycle. Также в Enum State реадизован метод itAtLeast(State), который отвечает на вопрос являтся State выше или равным от переданого как параметр.

Для работы с компонентом Lifecycle, нам нужно определить owner, то есть владельца жизненного цикла и observer, того кто на него будет подписан. У owner может быть любое количество подписчиков, также стоит отметить что observer будет проинформирован про изменение состояния, еще до того как у owner будет вызван метод super() на соответствующий метод жизненного цикла.

Owner должен реализовывать интерфейс LifecycleOwner, который содержит один метод getLifecycle(), который возвращает екземпляр класса холдера Lifecycle.

Observer должен реализовать интерфейс маркер LifecycleObserver.

Для самостоятельного обьявления кастомной Activity/Fragment, как owner-а, которые еще не поддерживают новый компонент и соответственно не имеют реализации Lifecycle, созданы: класс LifecycleRegistry и интерфейс LifecycleRegistryOwner.

Интерфейс LifecycleRegistryOwner, который в свою очередь расширяет интерфейс LifecycleOwner с единственым отличием в том что метод getLifecycle() возвращает LifecycleRegistry вместо Lifecycle.

Класс LifecycleRegistry, который являеться расширением Lifecycle и берет всю работу по поддержке на себя, нам лишь нужно создать его экземпляр.

Вот как выглядит реализация:

В пакете android.arch.lifecycle приведено 4 реализации owner: LifecycleActivity, LifecycleFragment, LifecycleService, ProcessLifecycleOwner.

LifecycleActivity — это FragmentActivity c реализацией LifecycleRegistryOwner. Является временным решением для упрощения работы и как сказано в документации будет пока Lifecycle не будет интегрирован с support library.

LifecycleFragment — это Fragment c пакета support.v4, который также как и в случае с LivecycleActivity реализовывает LifecycleRegistryOwner и является временным решением.

LifecycleService — это Service, который является также LifecycleOwner.

ProcessLifecycleOwner — это класс, который представляет Lifecycle всего процесса. Этот класс будет полезен если вам нужно отслеживать уход приложения в бэкграунд или возврат его на передний план.

Для того чтоб, связать owner и observer нужно у owner вызвать getLifecycle().addObserver(LifecycleObserver) Ниже я продемонстрирую работу всех этих классов. Для демонстрации, я создал класс SomeObserver, который будет логировать вызовы ON_CREATE и ON_STOP, я его буду использовать для всех видов owner-ов, поэтому для упрощения я добавил enum, константа с которого будет передаваться в конструктор и потом использоваться, чтоб отличить владельца по логам:

Читайте также:  Was the fable android

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

Листинг LifecycleService, он отрабатывает 5 секунд и завершается, его я запускаю из Application:

И для ProcessLifecycleOwner я решил расширить Application, как можно заметить ProcessLifecycleOwner сделан как singleton и являеться абсолютно самостоятельным компонентом:

Полный листинг вы можете посмотреть по линке: here

Также полезные ссылки: раз и два.

В следующей статье мы более подробно разберем LiveData компонент.

Источник

Урок 1. Lifecycle

В этом уроке рассмотрим возможности Lifecycle. Как подписаться на его события. Как узнать текущее состояние Activity.

Полный список уроков курса:

Довольно часто часть логики приложения завязана на жизненный цикл Activity. Мы включаем что-либо в методах onStart или onResume и выключаем в onPause или onStop.

У нас есть какой-то класс для работы с сервером. Он должен взаимодействовать с сервером, пока Activity открыто. Соответственно, мы будем подключать его к серверу при показе Activity и отключать при скрытии Activity.

Метод connect используется для подключения к серверу, disconnect — для отключения.

Вызываем эти методы в onStart и onStop в Activity.

Теперь MyServer будет подключен пока Activity видимо на экране.

Это вполне классическая, часто используемая схема. И в простом примере все выглядит неплохо. Но в сложных приложениях содержание методов onStart, onStop и пр. может состоять из нескольких десятков строк и быть достаточно запутанным. Гугл рекомендует выносить эту логику из Activity. Давайте посмотрим, как это можно сделать.

Lifecycle

У Activity есть метод getLifecycle, который возвращает объект Lifecycle. На этот объект можно подписать слушателей, которые будут получать уведомления при смене lifecycle-состояния Activity.

Activity и фрагменты в Support Library, начиная с версии 26.1.0 реализуют интерфейс LifecycleOwner. Именно этот интерфейс и добавляет им метод getLifecycle.

Т.е. у вас должна быть такая строка в build.gradle файле модуля, в секции dependencies

Либо используйте более свежую версию.

В нашем примере слушателем будет MyServer. Чтобы иметь возможность подписаться на Lifecycle, он должен наследовать интерфейс LifecycleObserver.

Обратите внимание, что интерфейс LifecycleObserver пустой. В нем нет кучи методов типа onStart, onStop и т.п. Мы просто помечаем в классе MyServer его же собственные методы аннотацией OnLifecycleEvent и указываем, при каком lifecycle-событии метод должен быть вызван.

В нашем примере, мы указываем, что метод connect должен вызываться в момент onStart, а метод disconnect — в момент onStop.

Осталось подписать экземпляр MyServer на Lifecycle.

В Activity методом getLifecycle получаем Lifecycle, и методом addObserver подписываем myServer.

А методы onStart и onStop в Activity нам больше не нужны, их можно удалить.

Теперь, при переходе Activity из состояния CREATED в состояние STARTED, его объект Lifecycle вызовет метод myServer.connect. А при переходе из STARTED в CREATED — Lifecycle вызовет myServer disconnect.

При этом в Acivity это потребовало от нас минимум кода — только подписать myServer на Lifecycle. Все остальное решает сам MyServer.

На схеме ниже вы можете увидеть какие состояние проходит Activity и какие события при этом вызываются.

Ничего нового тут для нас нет, все это азы Android. Тут вы можете видеть состояния и события. Они связаны очень просто — при переходе между состояниями происходят события.

Эти события мы указывали в аннотациях OnLifecycleEvent к методам объекта MyServer.

Полный список событий можно посмотреть в документации.

Отписаться от Lifecycle можно методом removeObserver.

Вы можете использовать событие ON_ANY для получения всех событий в одном методе

В этом случае все события будут вызывать этот метод.

Используйте входящий параметр event, чтобы определить, какое именно событие произошло

Читайте также:  Чтение doc для android

Состояние

Если вы хотите узнать текущее состояние Activity, то у его объекта Lifecycle есть метод getCurrentState:

Полный список состояний можно посмотреть в документации.

Также, вы можете проверить, что текущее состояние Activity не ниже определенного состояния.

Метод isAtLeast здесь проверяет, что состояние Activity не ниже, чем STARTED. Т.е. либо STARTED, либо RESUMED.

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Android Lifecycle-aware Architecture Components

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

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

Lifecycle, lifecycle-aware components and activities

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

Частично проблемы пересоздания активити можно избежать. Например, запретить пересоздание — поставить в манифесте настройку активити android:screenOrientation=«portrait». Но это решит проблемы только с пересозданием активити во время изменения конфигурации (например, смены ориентации экрана). Проблему того, что в какой-то момент операционной системе не хватит памяти и она уничтожит процесс с исполняемой активити этот способ не решает. Вернувшись к работе с приложением, первое, что увидит пользователь — критическую ошибку.

Так или иначе разработчику нужно позаботиться об обработке состояний жизненного цикла. На помощь приходят lifecycle-aware components. Архитектурные компоненты имеют стабильную версию 1.0 и их можно применять в production-разработке приложений.

Плюсы и минусы использования lifecycle-aware components

Рассмотрим практические плюсы и минусы использования компонентов.

Плюсов несомненно больше

  1. подключение нового сотрудника к команде разработки приложения. Все android разработчики знают и умеют пользоваться официальными библиотеками от компании Google. Не надо тратить время на обучение локальным решениям для поддержания архитектуры;
  2. меньше кода при разработке фичи;
  3. стабильность работы компонентов;
  4. улучшение стабильности работы приложения после внедрения компонентов.

Минусы

  1. время на ознакомление с компонентами и добавление в проект;
  2. добавился код для сопровождения архитектуры при разработке новой функции, но этот минус легко решается генерацией кода. Хорошие статьи на эту тему здесь и здесь.

Как работать с lifecycle-aware components?

Начиная с Support Library версии 26.1.0 фрагменты и активити из коробки реализуют интерфейс LifecycleOwner. Этот интерфейс имеет только один метод — getLifecycle().
Чтобы добавить наблюдателя за событиями жизненного цикла достаточно всего лишь в классе-наблюдателе реализовать интерфейс LifecycleObserver и написать в активити/фрагменте

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

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

Что же скрывается за парой строчек, как все работает, какие есть нюансы?
Найдем ответы на перечисленные ниже вопросы на примере фрагмента.

Читайте также:  Пропал значок блютуз андроид

Что возвращает фрагмент, реализуя интерфейс LifecycleOwner в методе getLifecycle()? Описание основных методов

Фрагмент имплементирует интерфейс LifecycleOwner, реализуя метод getLifecycle(): Lifecycle.

Lifecycle — абстрактный класс, определяющий объект, как объект имеющий жизненный цикл Android.

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

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

То есть если LifecycleOwner находится в состоянии Lifecycle.State.STARTED при добавлении LifecycleObserver, то последний получит два события Lifecycle.Event.ON_CREATE и Lifecycle.Event.ON_START.

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

Удаление наблюдателя из списка наблюдающих происходит в методе.

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

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

Возврат текущего состояния по запросу.

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

Существуют следующие виды State

INITIALIZED — данное состояние соответствует тому времени, когда сущность реализующая интерфейс LifecycleOwner создана, но метод onCreate() еше не был вызван.

CREATED — данное состояние активно после вызова метода onCreate() и до вызова onStop().

STARTED — данное состояние активно после вызова метода onStart() и до вызова onPause().

RESUMED — данное состояние наступает после вызова метода onResume().

DESTROYED — данное состояние наступает непосредственно перед вызовом onDestroy(). По наступлению этого состояния LifecycleOwner более не отправляет событий об изменении состояний.

Что происходит при добавлении наблюдателя к списку наблюдающих?

При вызове метода lifecycle.addObserver(observer) observer помещается в конструктор экземпляра класса-обертки ObserverWithState. Как понятно из названия класса — этот класс хранит observer с последним обработанным состоянием жизненного цикла. Изначально устанавливает состояние DESTROYED или INITIALIZED.

После создания экземпляра наблюдателя с последним обработанным состоянием жизненного цикла — пытаемся добавить наблюдателя в коллекцию FastSafeIterableMap методом putIfAbsent().

Если метод возвращает какой-то элемент — значит он уже есть в коллекции и добавлять повторно не надо. Что и происходит далее в коде. Работа метода addObserver() в случае имеющегося observer’а в списке прекращается. Также работа прекращается в том случае, если lifecycleOwner == null.

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

Что же за upEvent(state: State)? Замечу также, что существует downEvent(state: State). В зависимости от того, что сейчас происходит с жизненным циклом, опираясь на текущее состояние можно определить какое событие надо отправлять наблюдателю.

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

Как LifecycleOwner сообщает LifecycleObserver’у о событиях, происходящих с жизненным циклом фрагмента?

Фрагмент, реализующий интерфейс LifecycleOwner, содержит ряд доступных для вызова методов, соответствующих событиям жизненного цикла: такие как performCreate(savedInstanceState: Bundle), performStart(), performStop() и другие.

Класс FragmentManagerImpl вызывает данные методы, во фрагменте в свою очередь вызываются соответствующие методы onStart, onStop и прочие. А также вызываются методы класса LifecycleRegistry.

В классе LifecycleRegistry вычисляется состояние, о котором надо отправить следующее событие на основе принятого события.

И после этого вычисляется какой тип события надо отправить наблюдателю — upEvent(state: State) или downEvent(state: State)

Источник

Оцените статью