Emisión controlada de tiempo con Kotlin Flows
Clase 7 de 33 • Curso de Android: Integración de APIs nativas
Resumen
En Kotlin, manejar emisores de tiempo para proyectos de localización requiere conocer herramientas clave como Flows y Duration. Utilizando estas técnicas, puedes generar valores temporales precisos y constantes. Veamos cómo se implementan estas tecnologías de forma efectiva.
¿Qué son los flows y cómo funcionan en Kotlin?
Flows son herramientas de Kotlin diseñadas para realizar programación reactiva. Permiten emitir y coleccionar datos asíncronamente. Un flow builder facilita emitir valores cada cierto intervalo, por ejemplo cada 200 milisegundos.
Para utilizarlo de manera efectiva, se define:
- Una carpeta domain
.
- Una clase llamada timer
como objeto sencillo (singleton).
- Funciones específicas que encapsulan la lógica temporal.
¿Cómo crear un timer con Kotlin flows?
Debes definir una función timeAndEmits
con la siguiente lógica en Kotlin:
val lastEmitTime = System.currentTimeMillis()
while(true) {
delay(200)
val currentTime = System.currentTimeMillis()
val lapseTime = currentTime - lastEmitTime
emit(lapseTime.milliseconds)
lastEmitTime = currentTime
}
Esto permite generar intervalos exactos, enviando cada 200 milisegundos.
¿Cómo colectar valores emitidos por un flow?
Es esencial activar y coleccionar los valores emitidos desde tu Flow. La activación (Cold Flow) ocurre al utilizar operadores como collect
o launchIn
:
// Con lifecycleScope.launch
timer.timeAndEmits().collect {
Log.d("Flow Timer", "timer interval: $it")
}
// Alternativa con launchIn y onEach
timer.timeAndEmits().onEach {
Log.d("Flow Timer", "timer interval: $it")
}.launchIn(lifecycleScope)
¿Qué operador utilizar para combinar flujos en Kotlin?
Utilizando operadores como zip
, puedes combinar dos flujos diferentes para generar una emisión combinada y controlada:
timer.timeAndEmits()
.scan(Duration.ZERO) { accumulator, value -> accumulator + value }
.zip(timer.randomFlow()) { time, random -> Pair(time, random) }
.onEach {
Log.d("ZIP Flow", "Time: ${it.first}, Random: ${it.second}")
}.launchIn(lifecycleScope)
En este ejemplo:
- scan
acumula y suma tiempos anteriores para un control más preciso.
- zip
coordina cada emisión de los flujos, estableciendo dependencia de ambos para avanzar.
¿Cuál es la precisión al usar delay en flows?
Es importante considerar que delay
no es completamente exacto debido al tiempo de ejecución en líneas de código Kotlin, produciendo pequeñas variaciones de tiempo como 203 o 204 milisegundos en lugar de 200 exactos.