Android Architecture Components. Часть 2. Lifecycle
Как я уже упоминал в предыдущем материале, компонент Lifecycle призван упростить работу с жизненным циклом, а именно избежать коллбеков с Activity/Fragment в наш компонент, который должен реагировать на события жизненного цикла. В этой статье мы подробно разберем, как он устроен и как с ним работать.
Примечание: данный цикл статей был написан летом 2017 года, поэтому некоторая информация может быть немного устаревшей, но общая концепция архитектурных компонентов с тех пор не изменилась.
Сам компонент состоит из классов: 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, которому как параметр передается интересующее нас событие.
@OnLifecycleEvent(Lifecycle.Event.ON_ANY) void stateUpdated() { //будет вызваться при каждом изменении состояния жизненного цикла у оунера }
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 и берет всю работу по поддержке на себя, нам лишь нужно создать его экземпляр.
Вот как выглядит реализация:
class MyFragment : Fragment(), LifecycleRegistryOwner { val lifecycleRegistry = LifecycleRegistry(this) override fun getLifecycle(): LifecycleRegistry { return lifecycleRegistry } }
В пакете 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, константа с которого будет передаваться в конструктор и потом использоваться, чтобы отличить владельца по логам:
class SomeObserver( lifecycle: Lifecycle, private val owner: Owner ) : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onCreate() { Log.d(«Observer», owner + «: onCreate») } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onStop() { Log.d(«Observer», owner + «: onStop») } enum Owner { ACTIVITY, FRAGMENT, PROCESS, SERVICE } }
В целом же работа со всеми классами аналогичная. Все, что нам нужно, это создать экземпляр обсервера и подписать его на Lifecycle. В моей реализации мы передаем наш Lifecycle в конструктор обсервера, подпиской занимается уже сам обсервер. Данный подход является всего лишь делом вкуса и не более.
Листинг LifecycleActivity:
class MainActivity : LifecycleActivity() { val someObserver = SomeObserver(getLifecycle(), SomeObserver.Owner.ACTIVITY) override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) Log.d(«Owner», «onCreate») setContentView(R.layout.activity_main) } override fun onStop() { super.onStop() Log.d(«Owner», «onStop») } }
Листинг LifecycleFragment:
class MyFragment : LifecycleFragment() { val someObserver = SomeObserver(getLifecycle(), SomeObserver.Owner.FRAGMENT) override onCreateView( inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle ): View { return inflater.inflate(R.layout.fragment_my, container, false) } }
Листинг LifecycleService, он отрабатывает 5 секунд и завершается, его я запускаю из Application:
class MyService : LifecycleService() { lateinit val someObserver: SomeObserver override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { someObserver = SomeObserver(getLifecycle(), SomeObserver.Owner.SERVICE) Handler().postDelayed(Runnable { stopSelf() }, 5000) return super.onStartCommand(intent, flags, startId) } }
И для ProcessLifecycleOwner я решил расширить Application. Как можно заметить, ProcessLifecycleOwner сделан как singleton и является абсолютно самостоятельным компонентом:
class CustomApplication : Application() { private lateinit var processObserver: SomeObserver override fun onCreate() { super.onCreate() processObserver = SomeObserver(ProcessLifecycleOwner.getLifecycle(), SomeObserver.Owner.PROCESS) val intent = Intent(this, MyService::class.java) startService(intent) } }
Полный листинг вы можете посмотреть здесь. Также полезные ссылки: раз и два.
В следующей статье мы более подробно разберем LiveData компонент.
Android Architecture Components. Часть 1. Введение
Android Architecture Components. Часть 3. LiveData
Источник: Android Architecture Components. Часть 2. Lifecycle