A fondo con Flows & Channels — Parte 1: Streams

Julián Ezequiel Picó
Droid LATAM
Published in
6 min readJun 22, 2020

English version

En una serie de artículos, vamos a revisar a fondo las APIs de Channel y Flow que ofrece Kotlin.

Hay un poco de confusión por ahí, con gente tratando de definir si son cold streams, hot streams, están entre medio, o cualquier otro caso. Más allá de eso, lo que yo creo realmente es que no importa el tipo, sino que debemos entender como trabajan y que problemas resuelven. Luego, se podrá elegir uno u otro, pero estando seguro de uno mismo: vas a entender que estás haciendo.

La serie va a tener 5 artículos:

Por último, estuve trabajando en un Repositorio de GitHub donde van a poder encontrar algunos ejemplos de implementación de Flow y Channel, y una aplicación de ejemplo (que se parece mucho a un Twitter barato) donde emulamos un caso de uso real para aplicarlos.

Respecto a la aplicación de ejemplo, van a encontrar que en el repositorio hay 3 branches que implementan 3 soluciones diferentes para un mismo problema: hot streams. Van a poder encontrar usos básicos de Channel, BroadcastChannel y StateFlow.

Empecemos con la primer parte, Streams!

Streams

Hay mucha confusión cuando intentamos definir entre un hot y un cold stream. Siempre nos gusta decir oraciones definitivas, como “Flow para cold streams y Channel para hot streams”, pero cuando empezamos a trabajar con ellos, vemos que la línea que los separa es un poco difusa.

Cold & Hot Streams

Hay dos tipos de streams: los cold y los hot. En esta sección, voy a describir las principales diferencias y características de los mismos.

Existen muy buenos artículos (y muy concisos) que se pueden leer para entender un poco más sobre esto (y yo los utilicé para escribir esto): 1, 2, 3.

Principales diferencias

En mi opinión, existen 3 diferencias principales que nos ayudan a definir si un stream es hot o cold.

  • Donde se origina la información: la información puede ser generada dentro o fuera del stream. En otras palabras, la información existe (o no) sin importar si estamos utilizando o no el Stream.
  • Cuántos receptores pueden, al mismo tiempo, recibir la misma información: acá nos referimos a los mecanismos de unicast y multicast.
  • Laziness: no hay una traducción linda para esto, así que lo dejamos así. A lo que nos referimos es a cuándo el stream empieza a emitir información. Puede empezar cuando quiera (eager) o empieza cuando alguien se lo pide (lazy)?

Vamos a ver en los artículos siguiente que, tal vez, el último es la forma más conveniente de diferenciar streams en las APIs de Flow y Channels.

Cold Streams

Podemos decir que, en los cold streams, toda la información es producida dentro del stream.

Un cold stream tiene un único suscriptor y solo emite valores para ese suscriptor. Más aún, ese suscriptor es el que inicializa la emisión del stream. Podemos decir que este stream tiene un mecanismo de transmisión unicast.

Por cada nueva suscripción que recibe el stream, una nueva ejecución de su código es iniciada, y la misma va a ser independiente de las ejecuciones previas. Entonces, podemos decir que podemos tener múltiples instancias del mismo stream, y todas ellas son independientes entre sí.

Es importante notar que las líneas de código que van a ser ejecutadas para producir información son las mismas para todos los suscriptores, independientemente de quien sea.

Por último, podemos decir que un cold stream es un lazy stream: la emisión de valores comienza solo cuando alguien se suscribe a la misma. En otras palabras, comienza cuando alguien dice “hey, empezá a mandar información que estoy acá escuchando”.

Una buena analogía de un cold stream puede ser un CD:

  • Tenemos 1 CD por cada oyente → 1 stream para 1 suscriptor
  • El CD termina su reproducción cuando el oyente lo deja de reproducir → el stream termina cuando el suscriptor se desconecta
  • Las canciones son las mismas para todos los oyentes, no importa el momento en el que empiezan a escuchar → la información emitida es la misma para todos los suscriptores, no importa el momento en el que se suscriban

Espero que hayan entendido qué es un cold stream y como funciona. Ahora pasemos a los hot streams.

Hot Streams

Podemos decir que, en los hot streams, toda la información es generada por fuera del stream. Esta información puede existir sin el stream y, generalmente, viene de componentes externos.

Un hot stream puede tener cero o más suscriptores, y emite valores para todos ellos al mismo tiempo. Entonces, podemos decir que tenemos una transmisión de tipo multicast.

Solo hay una emisión para todos los suscriptores, y ninguno de ellos la inicializa, sino que sea sube a ella y empieza a escuchar. Dependiendo del momento en el que se suben, los suscriptores pueden recibir distinta información. Qué pasa si nadie está escuchando? Bueno, nada: la información se pierde, pero a nadie le importa!

Y, por último de nuevo, podemos decir que un hot stream es un eager stream: la emisión de valores comienza… siempre, no importa si hay alguien suscrito o no. En otras palabras, alguien dice “vamos a escuchar a ver que está transmitiendo”.

Una buena analogía de un hot stream puede ser una Estación de Radio:

  • Solo hay 1 estación de radio para todos los oyentes → 1 stream para todos los suscriptores
  • La radio continúa emitiendo aunque no haya nadie escuchando → el stream continúa aunque no haya suscriptores
  • La canción que el oyente escucha depende del momento en el que empieza a escuchar la radio → la información recibida por los suscriptores depende del momento en el que ellos se suscriben

Y eso es todo para hot streams. Notaron la diferencia, no?

In-between streams

Hay una definición que encontré por ahí y quiero mencionar.

Existen algunos cold streams que no son tan cold como la definición de cold menciona. Con estos, la información recibida por los suscriptores puede depender del momento en el que se suscriben. Algo así como una característica de los hot streams en un cold stream.

Diferencia entre Cold & Hot Streams por Roman Elizarov

Roman escribió un artículo bastante interesante que nos va a dar otra perspectiva para compara estos streams. Pueden verlo acá.

En el mismo, a grandes rasgos, el toma dos conceptos para diferenciar un cold stream de un hot stream: la existencia de la información y la sincronización.

Para hot streams (Channels), el dice:

  • La información existe sin que la aplicación la solicite. Por ejemplo, tenemos un servidor con una base de datos que guarda información y nos la devuelve a través de una API REST.
  • Con los hot streams, se necesita sincronización, porque hay diferentes actores que envían y consumen información, y necesitan estar sincronizados. En el caso de Channels, por ejemplo, se necesita sincronizar distintas coroutines que pueden tener distintos contextos y scopes.

Para cold streams (Flows), el dice:

  • La información no está activa ni existe antes de la solicitud del stream, ni luego de que el mismo termina.
  • No necesitamos manejar concurrencia o sincronización, ya que solo tenemos información que se emite de forma secuencial y no bloqueante.

Y eso es todo por ahora

Espero que, a estas alturas, ya puedan definir que es un hot stream y un cold stream.

Preparé este artículo introductorio solo para que, en los siguientes, podamos evaluar si un Flow o un Channel son realmente hot y cold streams, o si en lugar de eso lo importante es entender como funcionan y, desde ahí, elegir cual utilizar.

Nos leemos! Y, si te gustó, podes compartirlo!

Agradecimientos al equipo Android de MediaMonks por el feedback.

--

--