LiveData позволяет нам держать во вьюмодели стейт, который мы можем наблюдать из вьюхи.
Стейт – это некая динамическая переменная, отвечающая за состояние какой-то сущности. Например –
LiveData<List<Item>>, в которую будет приходить список, который мы хотим отобразить во вьюхе. Вьюха наблюдает
LiveData и реагирует на каждое изменение этого списка, всегда отображая актуальные данные.
ViewModel:
private val _items: MutableLiveData<List<Item>> = MutableLiveData()
val items: LiveData<List<Item>> = _items
View:
viewModel.items.observe(viewLifecycleOwner) {
adapter.submitList(it)
}
Преимущество LiveData в том, что она присылает свои изменения в наблюдателя
с учётом его жизненного цикла, и нам об этом париться не надо. Да и в целом,
LiveData – простая штука, хорошо работающая "из коробки", и позволяющая легко на начальных этапах реализовать наблюдаемый стейт для
MVVM.
Недостаток LiveData в том, что это класс из android-пакета, и использовать его, скажем, в
domain-слое по клину не очень-то хорошо, особенно если есть прицел на мультиплатформенность.
Flow позволяет нам реализовывать куда более гибкие и управляемые наблюдаемые конструкции,
без привязки к android-пакету.
Flow можно создавать самому, делая туда эмиты тогда, когда нужно, и настраивая так, как удобно. Его можно делать и холодным и горячим, доступным для одного подписчика или для многих, и многое другое.
ViewModel:
private val navigationEvents = MutableSharedFlow<NavigationEvent>(replay = 1)
View:
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.navigationEvents.collect {...}
}
}
Недостаток Flow в том, что его не стоит использовать, не почитав документацию и не разобравшись. Из коробки он может
не во всех кейсах работать интуитивно понятно. По незнанке довольно легко можно, к примеру, наткнуться на ситуацию, когда у вас
Flow "зависает" и перестаёт эмитить, и даже блокирует ваш поток, не давая исполняться коду, который написан в корутине вне
Flow после вызова
collect.
К чему может привести неверное использование
LiveData: если пытаться её использовать для, скажем, навигационных событий (показать / скрыть диалог или перейти на экран), сначала может показаться, что всё работает, но потом вы поймёте, что при смене конфигурации или возврате на экран мы будем получать старые данные (поскольку
LiveData держит стейт), или ловить другие странные баги.
Поэтому запомните: нужны одноразовые события – используйте для них
Flow. А
LiveData – для простых стейтов, напрямую связанных с UI.
#лайфхаки #android
Другие полезные постыОбучение android-разработке:
@andrdevnotes |
androidmentor.ru