Programación reactiva en Kotlin: de RxKotlin a las corutinas
La programación reactiva es un paradigma orientado al procesamiento asíncrono de flujos de datos y la propagación de cambios. En el ecosistema de Kotlin, este concepto se implementa de dos maneras principales: a través de la biblioteca RxKotlin (extensiones reactivas para Kotlin basadas en RxJava) y mediante el mecanismo integrado de corutinas con Flow. En este artículo, analizaremos ambos enfoques en detalle, sus características y ejemplos de uso.
¿Qué es la programación reactiva?
La idea principal de la programación reactiva es trabajar con los datos como flujos continuos (streams). En lugar de solicitar datos y esperar una respuesta, te suscribes a un flujo y reaccionas a cada nuevo evento. Esto es especialmente útil para aplicaciones de UI, procesamiento de entrada del usuario, solicitudes de red y trabajo con bases de datos.
Biblioteca RxKotlin
RxKotlin es un envoltorio sobre RxJava que añade extensiones convenientes para Kotlin, como lambdas, funciones de extensión y soporte para seguridad de nulos. Los tipos principales son:
Observable<T>— un flujo que puede emitir de 0 a N elementos y finalizar con un error o exitosamente.Single<T>— un flujo que emite exactamente un elemento o un error.Flowable<T>— un flujo con soporte de backpressure (control de velocidad de consumo).Completable— un flujo que solo finaliza (éxito/error) sin datos.
Ejemplo de RxKotlin
import io.reactivex.rxjava3.core.Observableimport io.reactivex.rxjava3.schedulers.Schedulers
fun main() { val observable = Observable.create<String> { emitter -> emitter.onNext("Hola") emitter.onNext("desde") emitter.onNext("RxKotlin") emitter.onComplete() }
observable .subscribeOn(Schedulers.io()) .observeOn(Schedulers.single()) .subscribe( { value -> println("Recibido: $value") }, { error -> println("Error: ${error.message}") }, { println("Flujo completado") } )
Thread.sleep(1000) // Esperamos la finalización de las operaciones asíncronas}En este ejemplo, se crea un Observable que emite tres cadenas y finaliza. Los operadores subscribeOn y observeOn gestionan los hilos de ejecución.
Corutinas y Flow en Kotlin
A partir de Kotlin 1.3, las corutinas pasaron a formar parte del lenguaje, y Flow (introducido en 1.3.70) es un flujo reactivo completamente integrado con las corutinas. Ventajas sobre RxKotlin:
- Menos sobrecarga (corutinas ligeras vs hilos de Java).
- Integración natural con funciones suspend.
- Soporte de concurrencia estructurada (cancelación automática al finalizar el scope).
- Sintaxis más limpia sin callbacks.
Ejemplo de Flow
import kotlinx.coroutines.*import kotlinx.coroutines.flow.*
fun main() = runBlocking { val flow = flow { for (i in 1..5) { delay(100) // Simulación de trabajo asíncrono emit(i) // Emitimos un elemento } }
flow .map { it * it } // Transformación .catch { e -> println("Error: $e") } .collect { value -> println("Cuadrado: $value") }}Flow es perezoso: los datos comienzan a generarse solo al llamar a collect. Los operadores map, filter, flatMapConcat funcionan igual que en Rx.
Comparación entre RxKotlin y Flow
| Característica | RxKotlin | Flow + corutinas |
|---|---|---|
| Dependencias |