Gruki Logo

Gruki - Documentación de Programación

Kotlin

Flujos en Kotlin: Flow y StateFlow explicados para todos

Descubre Flow y StateFlow en Kotlin: Guía fácil para entender cómo manejar flujos de datos de forma reactiva y eficiente. Aprende con ejemplos sencillos y explicaciones claras.

Imagínate que tienes un grifo (el 'productor') que puede dar agua (datos) en cualquier momento. Tú (el 'consumidor') quieres estar atento y usar esa agua cada vez que sale. Un Flow en Kotlin es como una tubería que conecta el grifo contigo. Te permite recibir el agua (los datos) a medida que el grifo la suelta, de forma organizada y sin que tengas que estar comprobando constantemente si hay agua.

En términos más técnicos, un Flow es un tipo de corrutina que puede emitir múltiples valores a lo largo del tiempo. Es ideal para manejar datos asíncronos y reactivos, como actualizaciones desde una base de datos, eventos de la interfaz de usuario o respuestas de una API.

Flow: El grifo de datos que fluye constantemente

Con Flow, creas una 'tubería' que sabe cómo obtener datos de algún lugar (el grifo). Luego, le dices a esa tubería qué hacer con esos datos una vez que llegan. Puedes transformar los datos, filtrarlos o combinarlos con otros flujos.

Piensa en un canal de YouTube. El creador (el productor) sube videos (datos) y tú (el consumidor) te suscribes al canal. Cada vez que sube un nuevo video, recibes una notificación. Flow es similar: te suscribes al flujo de datos y recibes las actualizaciones a medida que ocurren.

Puntos importantes:

  • Flow es 'frío'. Esto significa que no empieza a producir datos hasta que alguien se suscribe (lo 'recolecta'). Como un grifo que no gotea hasta que lo abres.
  • Flow es inmutable. No puedes cambiar los datos que emite directamente. En su lugar, creas nuevos flujos que transforman los datos existentes.

StateFlow: El estado actual del grifo

StateFlow es como tener un indicador que siempre muestra el estado actual del grifo. ¿Está abierto y dejando salir agua? ¿Está cerrado? StateFlow siempre guarda la última información disponible, incluso si no hay nadie mirándola en ese momento.

Imagina un termostato en tu casa. Siempre muestra la temperatura actual. Si preguntas cuál es la temperatura, te dará la última lectura, incluso si no estuviste mirando el termostato por un tiempo. StateFlow hace algo similar con los datos: siempre tiene el último valor emitido.

Puntos importantes:

  • StateFlow es 'caliente'. Siempre está listo para emitir su valor actual, incluso si nadie lo está recolectando activamente.
  • StateFlow requiere un valor inicial. Necesita saber cuál es el estado del grifo (el dato) antes de que empiece a funcionar.

¿Cuándo usar Flow y cuándo usar StateFlow?

Usa Flow cuando necesites manejar una secuencia de datos que se emiten con el tiempo y no necesitas recordar el último valor. Por ejemplo, para procesar una lista de archivos en un directorio.

Usa StateFlow cuando necesites mantener un estado actual que se puede observar. Por ejemplo, para representar el estado de carga de datos en una pantalla.

Puntos importantes:

  • Flow es ideal para casos de uso únicos donde no necesitas un valor almacenado.
  • StateFlow es perfecto para representar estados de la interfaz de usuario que necesitan ser compartidos y observados por múltiples componentes.

Ejemplos de Código

Ejemplo de cómo crear y recolectar un Flow que emite números del 1 al 5.

Lenguaje: Kotlin
kotlin

Explicación del código:

  1. Línea 1: import kotlinx.coroutines.delay: Importa la función 'delay' para simular una operación asíncrona.
  2. Línea 2: import kotlinx.coroutines.flow.*: Importa las clases y funciones necesarias para trabajar con Flows.
  3. Línea 3: import kotlinx.coroutines.runBlocking: Importa la función 'runBlocking' para ejecutar el código de la corrutina de forma síncrona en el hilo principal (necesario para el ejemplo).
  4. Línea 4: fun main() = runBlocking { ... }: Define la función principal que se ejecuta al iniciar el programa. 'runBlocking' asegura que la corrutina se complete antes de que termine el programa.
  5. Línea 5: val numberFlow: Flow<Int> = flow { ... }: Crea un Flow llamado 'numberFlow' que emitirá números enteros (Int). La función 'flow' construye el Flow.
  6. Línea 6: for (i in 1..5) { ... }: Un bucle que itera del 1 al 5.
  7. Línea 7: delay(1000): Suspende la corrutina durante 1000 milisegundos (1 segundo). Simula una operación que tarda un tiempo.
  8. Línea 8: emit(i): Emite el valor actual de 'i' al Flow. Esto es como el grifo dejando salir el agua.
  9. Línea 9: numberFlow.collect { ... }: Se suscribe al Flow y recibe cada valor emitido. El bloque '{ ... }' se ejecuta para cada valor.
  10. Línea 10: println("Recibido: $it"): Imprime el valor recibido en la consola. 'it' es el valor emitido por el Flow en cada iteración.

Ejemplo de cómo crear y usar un StateFlow para mantener el estado actual de un contador.

Lenguaje: Kotlin
kotlin

Explicación del código:

  1. Línea 1: import kotlinx.coroutines.*: Importa clases y funciones de corrutinas.
  2. Línea 2: import kotlinx.coroutines.flow.*: Importa clases y funciones de Flows.
  3. Línea 3: fun main() = runBlocking { ... }: Define la función principal, ejecutada en una corrutina bloqueante.
  4. Línea 4: val counterStateFlow = MutableStateFlow(0): Crea un StateFlow llamado 'counterStateFlow' con un valor inicial de 0. MutableStateFlow permite modificar su valor.
  5. Línea 5: CoroutineScope(Dispatchers.Default).launch { ... }: Inicia una nueva corrutina en segundo plano (Dispatchers.Default). Esto permite que el contador se actualice sin bloquear el hilo principal.
  6. Línea 6: for (i in 1..10) { ... }: Bucle que itera del 1 al 10.
  7. Línea 7: delay(500): Suspende la corrutina durante 500 milisegundos (0.5 segundos).
  8. Línea 8: counterStateFlow.value = i: Actualiza el valor del StateFlow con el valor actual de 'i'.
  9. Línea 9: counterStateFlow.collect { ... }: Se suscribe al StateFlow y recibe cada actualización del valor. El bloque '{ ... }' se ejecuta cada vez que cambia el valor.
  10. Línea 10: println("Contador: $it"): Imprime el valor actual del contador en la consola.

Recursos relacionados

Explora más contenido relacionado con Flujos en Kotlin: Flow y StateFlow para profundizar tus conocimientos.