Kotlin — Breve vistazo a Kotlin Flow
Kotlin Flow, según la documentación oficial, parte de la idea de brindar un mecanismo para retornar múltiples valores computados de forma asíncrona.
De una forma general consta de dos partes o componentes un Emisor y un Colector.
Algunas características que tienen estos flows o flujos son los siguientes:
- Actúan de forma fría o cold, es decir, el flujo no funcionará hasta que alguien recolecte los datos.
- Salvo que se emplee el builder
flowOn
no existe forma de cambiar de contexto, por lo cual un flujo mantendrá en el contexto de la corutina dentro de la cual se está ejecutando. - Tome en consideración que los flujos son secuenciales por naturaleza; sin embargo, se cuenta con el operador
buffer()
es posible ir acumulando los datos dentro de un flujo, esto es realmente útil cuando alguna de las operaciones toma más tiempo de lo esperado.
Flow Builders
Como todo flujo existe un punto de partida el cual está compuesto por los llamados flow builder.
Son tres funciones las que forman parte de estos flow builders:
flow{...}
el más básico crea un flujo a partir de un bloque suspendidoflowOf(values)
define un flujo emitiendo un conjunto fijo de valores.asFlow()
es una extension function aplicable a colecciones y secuencias que las convierte en emisores de valores
Intermediate Operators
Como te has de imaginar, en un flujo es posible efectuar operaciones de distintos tipos ya se para filtrar, transformar, etc. esto es posible gracias a los Intermediate Operators.
Algunos de los operadores intermedios con los que contamos son los siguientes:
map{}
retorna un flow conteniendo los resultados de la aplicación de una función de transformación por cada valor del flujo originalfilter{}
retorna un flow conteniendo solo los valores del flujo original que coinciden con una validación dadatransform{}
se puede emplear para realizar simples o complejas transformacionestake()
cancela la ejecución del flujo cuando el límite establecido es alcanzado
Terminal Flow Operators
En este punto es necesario recordar que los Flows son fríos (cold) lo cual se refiere a que el código no se ejecutará hasta que alguien recolecte los resultados. Justamente aquí es donde entran los operadores terminales de flujo (no se lee tan bonito en español, pero ni modo).
A continuación listaré algunos de estos operadores terminales:
collect{}
el más común, se encarga de recolectar los valores del flujo con una acción provista. Si alguna excepción ocurre durante la recolección o durante el flujo, esta excepción será relanzadas desde este métodoreduce{}
acumula los valores provistos por el flujo incluyendo el primer y aplicándoles la operación declarada durante la acumulaciónfold{}
acumula los valores del flujo partiendo de un elemento inicial declarado por el usuario y aplicando la operación declarada durante el proceso de acumulaciónfirst{}
retorna el primer elemento emitido por el flujo y, a continuación, cancela el flujosingle{}
básicamente dispara unIllegalStateException
si se emite más de un valortoList(), toSet()
estas funciones básicamente recolectan los valores y los convierte en una colección
Gracias a las dependencias ktx y en particular sobre androidx.lifecycle:lifecycle-livedata-ktx
contamos con una extension function adicional:
asLiveData()
esta función nos permite convertir un flow en un livedata
Recurso adicional
Algunas semanas atrás tuve la oportunidad de brindar una charla introductoria sobre Kotlin Flow que brindé como parte de Kotlin Nights La Paz; espero que les ayude a entender mejor este tema:
- Asynchronous Flow
https://kotlinlang.org/docs/reference/coroutines/flow.html
Si llegaste hasta aquí te invito también a que visites mi canal de Youtube donde estoy subiendo videos relacionados con Android y Kotlin