Kotlin Flow vs LiveData


10

В останньому вході / виводу Google Хосе Альцеррека та Ігіт Бояр сказали нам, що нам більше не слід використовувати LiveData для отримання даних. Тепер нам слід використовувати функції призупинення для одноразових випробувань і використовувати потоки Kotlin's Flow для створення потоку даних. Я погоджуюсь, що супроводи чудово підходять для отримання одного удару або інших операцій CRUD, таких як вставка тощо. Але у випадках, коли мені потрібен потік даних, я не розумію, які переваги дає мені Flow. Мені здається, що LiveData робить те саме.

Приклад із потоком:

ViewModel

val items = repository.fetchItems().asLiveData()

Сховище

fun fetchItems() = itemDao.getItems()

Дао

@Query("SELECT * FROM item")
fun getItems(): Flow<List<Item>>

Приклад з LiveData:

ViewModel

val items = repository.fetchItems()

Сховище

fun fetchItems() = itemDao.getItems()

Дао

@Query("SELECT * FROM item")
fun getItems(): LiveData<List<Item>>

Я також хотів би побачити кілька прикладів проектів, що використовують супровідні програми та Flow для роботи з Кімнатою чи Модернітом. Я знайшов лише зразок ToDo від Google, де підпрограми використовуються для отримання одного удару, а потім вручну переробляють дані про зміни.

Відповіді:


3

Flowє свого роду a reactive stream(як rxjava). Існує маса різних операторів на кшталт .map, buffer()(у будь-якому випадку менше немає. Оператора порівняно з rxJava). Отже, одна з головних відмінностей між LiveDataі Flowполягає в тому, що ви можете підписати карту computation / transformationв іншому потоці, використовуючи

 flowOn(Dispatcher....). 

Так, наприклад:

 flowOf("A","B","C").map { compute(it) }.flowOn(Dispatchers.IO).collect {...} // U can change the execution thread of the computation ( by default its in the same dispatcher as collect )

З LiveDataі map, вищенаведене не може бути досягнуто безпосередньо!

Тож рекомендується підтримувати потік на рівні сховища та робити живі дані мостом між інтерфейсом користувача та сховищем!

Основна відмінність полягає в тому, що flowє купа різних операторів, яких livedataнемає! Але знову ж таки, все залежить від того, як ви хочете побудувати ваш проект!


3

Як випливає з назви, ви можете мислити Flow як суцільний потік декількох асинхронно обчислених значень. Основна відмінність LiveData від Flow, з моєї точки зору, полягає в тому, що Потік постійно випускає результати, а LiveData оновлюватиметься, коли всі дані будуть отримані та поверне всі значення одразу. У вашому прикладі ви отримуєте єдині значення, на мою думку, це не зовсім те, для чого було створено Flow.

У мене немає прикладу Кімната, але скажімо, що ви показуєте щось, що вимагає часу, але ви хочете відображати результати під час надання та буферизацію наступних результатів.

private fun render(stuffToPlay: List<Any>): Flow<Sample> = flow {
     val sample = Sample()
     // computationally intensive operation on stuffToPlay
     Thread.sleep(2000)
     emit(sample)
}

Потім у вашій функції "Відтворення" ви можете, наприклад, відображати результати, де stuffToPlay - це перелік об'єктів для відображення, наприклад:

playbackJob = GlobalScope.launch(Dispatchers.Default) {

    render(stuffToPlay)
        .buffer(1000)   // tells the Flow how many values should be calculated in advance

        .onCompletion {
            // gets called when all stuff got played
        }
        .collect{sample ->
           // collect the next value in the buffered queue
           // e.g. display sample
        }
}

Важливою характеристикою Flow є те, що його код розробника (тут функція візуалізації) виконується лише тоді, коли він збирається, отже, його холод потік.

Ви також можете посилатися на документи в Асинхронному потоці

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.