Kotlin Flow vs LiveData

10

En la última E / S de Google, Jose Alcerreca y Yigit Boyar nos dijeron que ya no deberíamos usar LiveData para obtener datos. Ahora deberíamos usar las funciones de suspensión para las recuperaciones de una sola vez y usar Kotlin's Flow para crear un flujo de datos. Estoy de acuerdo en que las corutinas son excelentes para la extracción de una sola vez u otras operaciones CRUD, como la inserción, etc. Pero en los casos en que necesito un flujo de datos, no entiendo qué ventajas me ofrece Flow. Me parece que LiveData está haciendo lo mismo.

Ejemplo con flujo:

ViewModel

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

Repositorio

fun fetchItems() = itemDao.getItems()

Dao

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

Ejemplo con LiveData:

ViewModel

val items = repository.fetchItems()

Repositorio

fun fetchItems() = itemDao.getItems()

Dao

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

También me gustaría ver algunos ejemplos de proyectos que utilizan corutinas y Flow para trabajar con Room o Retrofit. Encontré solo una muestra de ToDo de Google donde las corutinas se usan para la recuperación de una sola vez y luego vuelven a buscar los datos manualmente al cambiar.

Dmitry Simakov
fuente

Respuestas:

3

Flowes una especie de reactive stream(como rxjava). Hay un montón de diferentes operadores como .map, buffer()(de todas formas menos no. Del operador en comparación con rxJava). Entonces, una de las principales diferencias entre LiveDatay Flowes que puedes suscribirte al mapa computation / transformationen algún otro hilo usando

 flowOn(Dispatcher....). 

Entonces, por ejemplo: -

 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 )

Con LiveDatay map, ¡lo anterior no se puede lograr directamente!

Por lo tanto, se recomienda mantener el flujo en el nivel del repositorio y hacer que los datos en vivo sean un puente entre la interfaz de usuario y el repositorio.

¡La principal diferencia es que flowtiene un montón de operadores diferentes que livedatano tiene! Pero, de nuevo, depende de ti cómo quieres construir tu proyecto.

Santanu Sur
fuente
3

Como su nombre lo indica, puede pensar en Flow como un flujo continuo de múltiples valores calculados asincrónicamente. La principal diferencia entre LiveData y Flow, desde mi punto de vista, es que un Flow emite resultados continuamente mientras LiveData se actualizará cuando se obtengan todos los datos y devolverá todos los valores a la vez. En su ejemplo, está obteniendo valores únicos, que no es exactamente para lo que se creó Flow en mi opinión.

No tengo un ejemplo de Room, pero digamos que está renderizando algo que lleva tiempo, pero desea mostrar los resultados mientras procesa y almacena los siguientes resultados.

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

Luego, en su función 'Reproducción', puede mostrar, por ejemplo, los resultados donde stuffToPlay es una Lista de objetos para representar, como:

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
        }
}

Una característica importante de Flow es que su código de constructor (aquí la función de renderizado) solo se ejecuta cuando se recopila, por lo tanto, está frío secuencia .

También puede consultar los documentos en Asynchronous Flow

nulldroid
fuente