Slide 1

Slide 1 text

Introducción a Kotlin Flows Armando Picón Senior Android Developer at Cornershop Inc. @devpicon https://linktr.ee/devpicon

Slide 2

Slide 2 text

Flows? • Los Kotlin Flows deberían ser empleado en aquellos casos en los que se precisa el retorno de múltiples valor computados asíncronamente • Los flujos como tal requieren de alguien que recolecte los resultados, por eso se indica que son “fríos” (cold) • Flow está inspirado en frameworks reactivos como RxJava

Slide 3

Slide 3 text

Emitter Collector

Slide 4

Slide 4 text

Emitter Collector flow{ emit() } collect()

Slide 5

Slide 5 text

Emitter Collector flow{ emit() } collect() Flow builder

Slide 6

Slide 6 text

Flow builders • flow{} -> el más básico, permite crear un flow desde un bloque que se puede suspender • flowOf() -> establece un flow mediante la emisión de un grupo preestablecido de valores. • .asFlow() -> es una función de extensión que permite generar un flow a partir de una colección o secuencias.

Slide 7

Slide 7 text

flow{ emit() } collect() Flow builder Emitter Collector

Slide 8

Slide 8 text

flow{ emit() } collect() map{} filter{} transform{} take() Flow builder Emitter Collector

Slide 9

Slide 9 text

flow{ emit() } collect() operadores intermedios map{} filter{} transform{} take() Flow builder Emitter Collector

Slide 10

Slide 10 text

Operadores intermedios Intermediate flow operators • map{} -> retorna un flow conteniendo el resultado de la aplicación de una función de transformación a cada valor del flujo • filter{} -> retorna un flow conteniendo solo los valores del flujo original que coinciden con la condición • transform{} -> puede se empleado para realizar tanto transformaciones simples como complejas. Podemos emitir valores por una cantidad arbitraria de veces • take() -> cancela la ejecución del flujo cuando el límite correspondiene ha sido alcanzado

Slide 11

Slide 11 text

flow{ emit() } collect() map{} filter{} transform{} take() Flow builder operadores intermedios Emitter Collector

Slide 12

Slide 12 text

flow{ emit() } collect() Terminal flow operator map{} filter{} transform{} take() Flow builder operadores intermedios Emitter Collector

Slide 13

Slide 13 text

Operadores terminales (Terminal flow operators) • collect{} -> recolecta el flujo con una acción provista. Si cualquier excepción ocurre durante la recolección o en el flujo, esta excepción será relanzada desde esta función • reduce{} -> acumula los valores partiendo con el primer elemento y aplicando el operador definido al valor acumulador y a cada elemento. Va a tirar un NoSuchElementException si el flujo se encontraba vacío • fold{} -> acumula valores a partir de un valor inicial establecido y aplicando la operación a medida que se va acumulando cada elemento Son funciones suspendidas que dan comienzo a la recolección de datos del flujo.

Slide 14

Slide 14 text

Operadores terminales (Terminal flow operators) • first{} -> retorna el primer elemento emitido por el flujo y tras ello cancela el flujo. Lanza un NoSuchElementException si el flujo se encontraba vacío • single{} -> espera a que solo un valor sea publicado. Lanza un NoSuchElementException para un flujo vacío y un IllegalStateException si el flujo contiene más de un elemento Son funciones suspendidas que dan comienzo a la recolección de datos del flujo.

Slide 15

Slide 15 text

Operadores terminales (Terminal flow operators) • toList(), toSet() -> Recolecta los valores del flujo y los convierte en una colección. Son funciones suspendidas que dan comienzo a la recolección de datos del flujo.

Slide 16

Slide 16 text

Operadores terminales (Terminal flow operators) • toList(), toSet() -> Recolecta los valores del flujo y los convierte en una colección. • asLiveData() -> Recolecta los valores del flujo y los convierte en un livedata Son funciones suspendidas que dan comienzo a la recolección de datos del flujo.

Slide 17

Slide 17 text

Preservación de contexto (Context preservation) • Las recolecciones siempre suceden en el contexto de la corutina que lo está invocando • No puedes cambiar manualmente el contexto cuando una recolección está siendo ejecutada • La única forma de cambiar el contexto del emisor es medianteel uso de la función flowOn()

Slide 18

Slide 18 text

Los flujos son secuenciales (Flows are sequential) • Cada recolección de un flujo es efectuado de manera secuencial a menos que se emplee algún operador especial para que múltiples flujos sean empleados • ¿Qué sucede si una recolección y una emisión son lentas?

Slide 19

Slide 19 text

Emitter Collector delay(100) emit delay(100) println(it) delay(100) emit delay(100)

Slide 20

Slide 20 text

¿Podría ser la ejecución secuencial un problema? (Could be the sequential execution an issue?) • La ejecución secuencial podría ser un potencial problema cuando tanto el emisor como el recolector toman mucho tiempo para procesar cada elemento • Tomemos en consideración que los flujos se ejecutan en el contexto dentro de la misma corutina • ¿Podríamos desacoplar el emisor del recolector sin cambiar radicalmente el código?

Slide 21

Slide 21 text

Los desafíos del desacoplamiento del emisor y el recolector (Challenges to decouple the emitter and the collector) • Ejecutar el emisor en una corutina separada podría ocasionar que ambas se tornen concurrentes • Con dos corutinas separadas necesitaríamos de algún medio de comunicación que las conecte • Aquí es donde los canales (channels) entran a escena proveyendo de un mecanismo donde podemos enviar elemento de un emisor y recibirlo en otro punto a través de un canal

Slide 22

Slide 22 text

Operador Buffer (Buffer operator) • El uso de un buffer permite manejar este tipo de situaciones, mediante el uso de un canal (channel) se consigue acumular y consumir los elementos a medida que se van generando • El operador buffer crea una corutina separada durante la ejecución del flujo

Slide 23

Slide 23 text

Emitter Collector delay(100) emit delay(100) println(it) delay(100) emit delay(100) println(it) delay(100) emit

Slide 24

Slide 24 text

Transparencia de excepciones (Exception transparency) • Las excepciones pueden ser relanzadas • Las excepciones también podrían emitirse desde el bloque de un catch{} • Las excepciones pueden ser ignoradas, registradas o procesadas por algún otro código

Slide 25

Slide 25 text

Show me some code dude! https://github.com/DevPicon/kotlin-marvel-hero-finder

Slide 26

Slide 26 text

Referencias • Asynchronous Flow https://kotlinlang.org/docs/reference/coroutines/flow.html • Cold flows, hot channels https://medium.com/@elizarov/cold-flows-hot-channels-d74769805f9 • Simple design of Kotlin Flow https://medium.com/@elizarov/simple-design-of-kotlin-flow-4725e7398c4c • Kotlin Flows and Coroutines https://medium.com/@elizarov/kotlin-flows-and-coroutines-256260fb3bdb

Slide 27

Slide 27 text

Lecturas recomendadas • A fondo con Flows & Channels — Parte 1: Streams https://medium.com/droid-latam/a-fondo-con-flows-channels-parte-1-streams-475d4ce0b909 • A fondo con Flows & Channels — Parte 2: Flows https://medium.com/droid-latam/a-fondo-con-flows-channels-parte-2-flows-189b88a92141 • A fondo con Flows & Channels — Parte 3: Channels https://medium.com/droid-latam/a-fondo-con-flows-channels-parte-3-channels-c4765ae5d19f • A fondo con Flows & Channels — Parte 4: BroadcastChannels https://medium.com/droid-latam/a-fondo-con-flows-channels-parte-4-broadcastchannels-6cd92e8dbef7 • A fondo con Flows & Channels — Parte 5: StateFlows https://medium.com/droid-latam/a-fondo-con-flows-channels-parte-5-stateflows-5ba84db94871 La serie de @juliann_ezeqiel

Slide 28

Slide 28 text

Lecturas recomendadas • Asynchronous development in Android: RxJava vs Kotlin Flow https://medium.com/makingtuenti/asynchronous-development-in-android-rxja va-vs-kotlin-flow-f7fdf2e2f81b • From RxJava 2 to Kotlin Flow: Threading https://proandroiddev.com/from-rxjava-2-to-kotlin-flow-threading-8618867e1 955 • The Real Kotlin Flow benefits over RxJava https://proandroiddev.com/the-real-kotlin-flow-benefits-over-rxjava-c19b99ba 6eb9

Slide 29

Slide 29 text

Codalot Podcast anchor.fm/codalot youtube.com/devpicon ¡Gracias! /devpicon