Android arch lifecycle runtime

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, константа с которого будет передаваться в конструктор и потом использоваться, чтоб отличить владельца по логам:

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

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

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

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

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

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

Источник

Exploring new Coroutines and Lifecycle Architectural Components integration on Android

G oogle I/O brought various interesting things for Android Developers: there’s the cutting edge JetPack Compose, the new F̶l̶u̶t̶t̶e̶r̶ ̶i̶n̶ ̶K̶o̶t̶l̶i̶n̶ declarative toolkit to build UI using composable Widgets, but it’s still in early early stage of development and it’s not intended for production use in the short term.

Something that’s actually more interesting for Kotlin Developers, is the new integration between Coroutines and Arch Components, lifecycle and liveData in primis and by now I think you’ve already guessed what is the topic we’re going to cover in this article 🙂

First of all, to get all the new features, you need to use version androidx.lifecycle:*:2.2.0-alpha01 or more of the lifecycle libraries.

But that’s not all. If you look at the docs you’ll find out there’s a new Coroutine scope called lifecycleScope and a new LiveData building block.

Читайте также:  Crazen texture pack geometry dash android

Including that, is actually quite tricky… Searching online it’s not very hard to find comments like this:

There’s in fact another library that Google silently released that enables those features called lifecycle-runtime-ktx that you need to import as well.

So, the full list of imports required to try all the features listed in this post is:

I’m assuming you’re already familiar with Coroutines basics on Android. If you’re not, check out this awesome series of Medium posts by Sean McQuillan.

What’s new in androidx.lifecycle:*:2.2.0-alpha01

Coroutine Scope and ViewModelScope

You probably know that Coroutines run in a scope that will handle for you useful things like get uncaught exceptions and cancellation to make sure you never leak a Coroutine.

If you need to call a suspending function from a ViewModel, instead of manually creating a new scope, there’s one already ready for you: viewModelScope is bound to ViewModel’s lifecycle and will handle for you cancellation when the ViewModel onClear() is called. You can easily access this scope from an extension function available on viewmodel-ktx library.

Here you can see an example of a function to sign in the user using Firebase Auth.

Note that Firebase Auth’s method signInWithEmailAndPassword returns a Task that you can conveniently convert to a cancellable suspending function using await() from kotlinx-coroutines-play-services .

LifecycleScope

Starting from lifecycle-runtime-ktx:2.2.0-alpha1, there is also a similar scope for all Lifecycle objects like Activities and Fragments. Again, all the coroutines in that scope will be canceled when the Lifecycle is destroyed.

Be aware that lifecycleScope is convenient when dealing with UI events like, for example, showing a tip for the user and hiding it after a small delay.

Without using Coroutines and lifecycleScope, this would be:

You should not use lifecycleScope for other tasks like retrieving data from repositories or making long computations. This is because those scopes are bound to Activities and Fragments lifecycles and will cancel the coroutines inside them when, for instance, there’s a configuration change.

In short, you will end up with your network request canceled if the user rotates the phone, defeating the whole purpose of a ViewModel behind an Activity. That’s why it’s better to call those methods inside the viewModelScope and let the activity only observe the LiveData value. We’ll come back to this later.

But that’s not all. You may want to run those coroutines only if your Lifecycle is in a certain state.

Let’s refresh our memory with all possible lifecycle states from Android docs:

Again, reading from the docs, you’ll notice that:

When a Fragment state is saved via onSaveInstanceState() , it’s UI is considered immutable until ON_START is called. Trying to modify the UI after the state is saved is likely to cause inconsistencies in the navigation state of your application which is why FragmentManager throws an exception if the app runs a FragmentTransaction after state is saved.

So if you need to run a FragmentTransaction inside your coroutine scope, you need your Fragment lifecycle to be at least STARTED.

You can achieve this using lifecycleScope.launchWhenStarted to ensure your code will be called at the right time:

LiveData

One of the big news introduced with livedata-2.1.0-alpha1, is interoperability between LiveData and Coroutines.

Let’s start with an example. You want to make a network request and expose the result to an Activity with a LiveData. The activity will start observing the LiveData which will be empty at first and will be notified when data is available from the network call.

Starting from 2.2.0-alpha01, LiveData has a new building block that will automagically execute when the LiveData becomes active. No need to add that you’ll observe LiveData using a LifecycleOwner, so it will know when to stop executing and cancel the coroutines inside the building block. That’s very similar to lifecycleScope we’ve seen earlier.

Inside the LiveData building block, you can use emit() to set a value to the LiveData. Since LiveData allows only setting values from the main thread, emit() is always executed on this one.

So, the previous example will now become:

This is a lot more simple and concise. Also note that we’re making a network request, so it would be better to run our suspending function on the IO Dispatcher. We can do that passing the dispatcher we want to use as parameter of the liveData block:

Simple as that. No need to switch dispatcher to Dispatchers.Main for the emit() function, since it will always automatically run on the main thread.

By the way, you might want to know that Retrofit now supports suspending functions. Well, retrofit:2.5.1-SNAPSHOT does, so if you’re more into stable releases, check out Jake Wharton’s Kotlin Coroutine Adapter.

Let’s see another example. Now you want to load first a cached copy of some data and then start getting the updated values, for example, from Firebase Database.

The flow would be:

  1. Emit cached copy ( Data)
  2. Emit Firebase Database data ( LiveData)

Since Firebase already returns a LiveData, you’ll end with another LiveData in your ViewModel: the one from Firebase, and the one you’re building which has just emitted the cached data.

With emitSource() you can not only emit a single value, but attach your LiveData to another LiveData and start emitting from it. Anyway, each emit() or emitSource() call will remove the previously added source.

Читайте также:  Проверка состояния аккумулятора андроид команда

The activity that’s observing the someData object, will quickly receive the cached data on the device and update the UI. Then, the LiveData itself will take care of making the network request and replace the cached data with a new live stream of data, that will eventually trigger the Activity observer and update the UI with the updated info.

A similar example would be loading local data, fetching new data from a server and update cached data with the new one.

If you’re using Room, you probably know you can get LiveData out from a query:

In this case, you’re feeding the post LiveData with Room’s data. When an updated version of the post will be available, it will update the copy in the local database and Room will automatically emit the value.

We said early that LiveData, after a short timeout, will cancel all the coroutines that are still running when the attached lifecycle of the observer is destroyed, so no need to worry for that. You can adjust that timeout passing a Long as parameter with the milliseconds to wait before cancellation.

Recap

So now you have some new Coroutine Scopes, similar to viewModelScope, the lifecycleScopes bound to Activities, Fragments, View… in short every object that has a LifecycleOwner attached. You can use those to write UI related coroutines and eventually specify in which state of lifecycle run them.

You also have a new LiveData building block that comes with a Scope that lets you run coroutines and emit data from inside. Those coroutines will cancel after a small delay when the lifecycle of the object that is observing livedata is destroyed.

But await(), there’s more!

If you want to know more about Kotlin Coroutines with other Architectural Components here’s the official documentation on Android Developers. There’s also a good I/O session about the same topic available on YouTube.

Источник

Русские Блоги

Android-Lifecycle супер анализ-жизненный цикл этих вещей

Как мы все знаем, все, что Android должен показывать пользователям, содержит концепцию жизненного цикла. Например, Activity, Fragment и View тесно связаны с жизненным циклом. В функции жизненного цикла каждый из них завершает создание, рендеринг и уничтожение.

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

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

Эта статья длинная, пожалуйста, прочтите ее терпеливо.

Что такое жизненный цикл?

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

Жизненный цикл был включен в новую версию AppCompatActivity и FragmentИЖизненный цикл также является основой двух других компонентов LiveData и ViewModel в Android Jetpack., То есть эта библиотека может продолжать сопровождать нашу последующую разработку, так почему бы не изучить ее?

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

1. Используйте

1. Добавьте зависимости:

В build.gradle в каталоге приложения или модуля добавьте зависимости:

2. Реализовать интерфейс LifecycleObserver

Во-первых, нам нужно добитьсяLifecycleObserverЭтот интерфейс, а затем добавить в наш метод@OnLifecycleEventАннотация, значение примечания указывает, какой функции жизненного цикла соответствует метод. Здесь мы добавляем все функции жизненного цикла и просто печатаем журнал.

Я думаю, что кто-то спросит, почему этот класс называется Java7Observer? Это верно, потому что в Java8 официальной рекомендацией является использование другого метода:

Причина проста: в исходном коде Lifecycle есть комментарий:

* If you use Java 7 Language, Lifecycle events are observed using annotations. * Once Java 8 Language becomes mainstream on Android, annotations will be deprecated, so between * <@link DefaultLifecycleObserver>and annotations, * you must always prefer <@code DefaultLifecycleObserver>. *

Перевод такой: «Если вы используете java7, то вы используете аннотации, но я говорю вам, что как только java8 работает, ваши аннотации устаревают, и я советую вам использовать DefaultLifecycleObserver»

3. Добавьте LifecycleObserver в список наблюдателей Lifecycle.

Если вы используете новую версию AppcompatActivity (> 26.1.0), вы можете написать:

Если ваша AppCompatActivity не обновлена ​​до последней версии, вам необходимо реализоватьLifecycleOwnerИнтерфейс и распространение событий в функции жизненного цикла Activity

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

Можете ли вы привести пример знакомства?

MVP, должно быть, использовался всеми или слышал, что уровень View связывается со слоем Model через уровень Presenter, поэтому, если уровень Presenter делает что-то за пределами жизненного цикла View и не освобождает память вовремя, это вызовет утечку памяти.

Итак, оригинальный Presenter, в ответ на жизненный цикл, мог бы написать:

Сначала определите все функции жизненного цикла

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

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

Читайте также:  Как полностью удалить файл андроид

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

2. Знать, что это и почему

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

Сначала посмотрите на официальную фотографию:

Вы можете увидеть два очень заметных слова:StateиEventЭто также две концепции на протяжении жизненного цикла: состояние и событие.

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

State:Статус является индикатором состояния, соответствующим жизненному циклу действия в жизненном цикле, и, как видно из рисунка, он имеет пять состояний: ИНИЦИАЛИЗИРОВАННЫЙ, УНИЧТОЖЕННЫЙ, СОЗДАННЫЙ, ЗАПУЩЕННЫЙ и ВОЗОБНОВЛЕННЫЙ.

  • INITIALIZED: Соответствует жизненному циклу до создания действия
  • DESTROYED: Соответствует деятельности onDestroy
  • CREATED: Соответствует жизненному циклу Activity от onCreate до onStop
  • STARTED: Соответствует жизненному циклу от onStart до onPause of Activity
  • RESUMED: Соответствует активности onResume

Event:Событие, при изменении состояния, жизненный цикл отправляет события зарегистрированному LifecycleObserver, например: Когда состояниеINITIALIZEDИзменить наCREATED, Он будет генерировать событие ON_CREATE.

Следовательно, чтобы понять жизненный цикл, вам нужно понять две вещи:

  1. Как государство связано с жизненным циклом Деятельности / Фрагмента?
  2. Как события Event распространяются на LifecycleObserver?

Хорошо, с этими двумя вопросами мы начали смотреть на исходный код:

1. Начните с getLifecycle () AppCompatActivity

Непосредственно Ctrl + левый щелчок, чтобы следовать исходному коду. Поскольку AppCompatActivity наследует от SupportActivity, мы обнаружили, что AppCompatActivity.getLifecycle () наконец-то позиционируется в методе SupportActivity.getLifecycle ().

Это не сложно увидеть:

  1. В конце концов, getLifecycle () возвращает объект LifecycleRegistry, поэтому все операции над LifecycleObserver выполняются LifecycleRegistry.
  2. В методе onCreate () мы также увиделиReportFragment.injectIfNeededIn(this)Сделайте отметку сначала, а потом

2.LifecycleRegistry

Буквально: реестр жизненного цикла

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

Давайте посмотрим, как новая версия AppCompatActivity распределяет события в LifecycleRegistry. Запомните эту логику в SupportActivity:

Давайте посмотрим, что такое ReportFragment

3.ReportFragment

Как видите, SupportActivity добавила ReportFragment без страницы в функцию жизненного цикла ReportFragment, которая называетсяLifecycleRegistry.handleLifecycleEvent()Способ распространения событий жизненного цикла. Подводя итог с изображением это:

Добавлен ReportFragment в AppCompatActivity, который вызывается при изменении его жизненного цикла
LifecycleRegistry.handleLifecycleEvent()Метод информирует LifecycleRegistry об изменении состояния,
Внутренний вызов LifecycleRegistrymoveToState()Изменить состояние,
и позвоните каждомуLifecycleObserver.onStateChange()Способ уведомления об изменениях жизненного цикла.

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

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

  • Когда мы не наследуем новую версию AppCompatActivity, как Lifecycle распределяет события жизненного цикла через ReportFragment?

Здесь мы напрямую используем мощную функцию поиска AndroidStudio, а alt + F7 поиска по вызывающему объекту ReportFragment мы обнаружили: помимо SupportActivity, есть два места для использования ReportFragment:LifecycleDispatcherиProcessLifecycleOwner

4.LifecycleDispatcher

Буквально: дистрибьютор жизненного цикла

Вы можете видеть, что LifecycleDispatcher зарегистрированApplication.registerActivityLifecycleCallbacksДля мониторинга обратного вызова жизненного цикла деятельности.

  • Добавьте ReportFragment в onActivityCreated () и передайте жизненный цикл Activity в ReportFragment для распространения в LifecycleRegistry.
  • В onActivityStopped () и onActivitySaveInstanceState () установите для состояния активности и всех его дочерних фрагментов значение CREATED.

5.ProcessLifecycleOwner

Прямое значение: владелец жизненного цикла нити

Согласно официальным заметкам, мы можем узнать:

  • ProcessLifecycleOwner используется для мониторинга жизненного цикла приложения, поэтому он распространяет событие ON_CREATE только один раз и не распространяет событие ON_DESTROY.
  • ProcessLifecycleOwner использует метод Handle.postDelayed () в методах Activity onResume и onStop, чтобы иметь дело с реконструкцией Activity, такой как горизонтальное и вертикальное переключение экрана, не будет отправлять события.
  • ProcessLifecycleOwner обычно используется для определения того, находится ли приложение на переднем плане или в фоновом режиме. Однако, поскольку используется Handle.postDelayed (), это решение не является немедленным, и по умолчанию задержка составляет 700 мс.
  • ProcessLifecycleOwner и LifecycleDispatcher, зарегистрировав Application.registerActivityLifecycleCallbacks для мониторинга обратных вызовов жизненного цикла действия, чтобы добавить ReportFragment к каждому действию.

Итак, снова возникает вопрос: где инициализируются классы ProcessLifecycleOwner и LifecycleDispatcher?

Мы можем видеть из исходного кода, что их точки входаinit(Context)Продолжая искать исходный код, мы нашли:

Очевидно, жизненный цикл автоматически в нашемAndroidManifest.xmlДобавилContentProviderДля инициализацииProcessLifecycleOwnerиLifecycleDispatcherПреимущество этого в том, что оно не требует от нас отображения вызова в Приложении и не требует от нас написания строки кода.

резюме

Вернемся к нашим первым двум вопросам:

  • Как государство связано с жизненным циклом Деятельности / Фрагмента?

Добавить один в активностьReportFragment(Если ваша активность наследует AppCompatActivity,
будет добавлено в onCreate () родительского классаReportFragmentВ противном случаеLifecycleDispatcherДобавить),
вReportFragmentВызывается в функции жизненного циклаLifecycleRegistry.handleLifecycleEvent() Изменение методаState

  • Как события Event распространяются на LifecycleObserver?

LifecycleRegistryПри полученииhandleLifecycleEvent() Позже,
внутренний вызовmoveToState() Метод, измените значение состояния, каждый раз, когда изменяется значение состояния, оно будет вызываться
LifecycleObserver.onStateChanged() Метод распространения события наLifecycleObserver

До знаний? Навыки обучения? Следите за официальным аккаунтом WeChat:

Источник

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