Урок 6. AndroidDev на Kotlin. Activity Lifecycle. Интерфейс LifecycleObserver

Наглядное отображение событий жизненного цикла

Запустите приложение в эмуляторе или на смартфоне и посмотрите, как будут появляться тосты с информацией о состояниях активити и событиях.

Когда активити запускается системой, оно инициализируется (INITIALIZED) и происходит событие ON_CREATE. При этом активити переходит к состоянию “создано” (CREATED). Далее происходит событие ON_START и активити переходит к состоянию “запущено” (STARTED). Следующее событие ON_RESUME. Активити переходит в состояние – RESUMED (возобновлено) – выходит на передний план, получает фокус и отображается пользователю. Если активити в процессе работы теряет фокус и частично перекрывается, например, диалоговым окном или другим активити, то переходит обратно в состояние STARTED. При этом происходит событие ON_PAUSE. В этом состоянии активити приостанавливается, но может быть все еще видимым на экране, например, в многооконном режиме. Если же активити полностью перекрыто, то система его останавливает и переводит в состояние CREATED. Выполняется событие ON_STOP. Активити пока не уничтожается системой и может в любой момент возобновить работу. При возврате к нему выполняется колбэк onRestart() и затем происходят события ON_START и ON_RESUME с возобновлением соответствующих состояний.

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

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

Имейте в виду, что могут быть ситуации, когда активити может быть уничтожено без вызова некоторых колбеков. Например, если в теле функции onCreate() прописать вызов функции finish(), то после onCreate() сразу будет вызван onDestroy(). Однако и onDestroy() может не быть вызван в некоторых случаях при уничтожении активити системой.

Почему так не нужно делать?

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

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

Интерфейс LifecycleObserver

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

Чтобы более тесно на практике познакомиться с чистой архитектурой и архитектурными компонентами, записывайтесь на продвинутый курс по разработке приложения «Чат-мессенжер»

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

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

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

Для этой цели служит интерфейс LifecycleObserver, который мы реализуем в новом классе MyObserver. Интерфейс LifecycleObserver не имеет методов. Мы можем создать любую функцию и привязать ее к жизненному циклу активити. Для привязки служит аннотация @OnLifecycleEvent, которая принимает объект Lifecycle с перечислением Event, содержащим константы для каждого события жизненного цикла.

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

Также есть константа ON_ANY для реагирования на все события жизненного цикла.

Такая функция будет выводить в лог все события жизненного цикла активити:

@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    fun onAny(source: LifecycleOwner, event: Lifecycle.Event) {
        Log.d("TAG", event.toString())
    }

Чтобы подписать этот класс на события жизненного цикла, в MainActivity объявляем переменную класса MyObserver с поздней инициализацией:

lateinit var myObserver: MyObserver

В теле функции onCreate() инициализируем переменную и подписываем на объект lifecycle:

myObserver = MyObserver()
lifecycle.addObserver(myObserver)

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

Наш урок подошел к концу. Исходный код проекта можно посмотреть по ссылке.

Следующий урок, в котором мы рассматриваем сохранение и передачу состояния активити при изменении конфигурации:

Додати коментар