RxJava es una biblioteca de programación reactiva para Java y Android que implementa el patrón Observer a través de Observable y Observer. Según ReactiveX GitHub, 2026, RxJava permite manejar flujos de datos y eventos asíncronos mediante cadenas de operadores. La unidad básica es Observable, que emite datos a un Observer a través de una cadena de transformaciones. RxJava 3 es la versión estable actual con soporte para Java 8 lambda, Reactive Streams e integración con Android mediante RxAndroid.
Puntos clave
RxJava es la implementación Java de la especificación ReactiveX, una biblioteca para programación asíncrona mediante flujos observables (Observable). RxJava 2 se lanzó en 2016 con soporte de Reactive Streams (Flowable) y la separación en rx.Observable e io.reactivex.Observable. RxJava 3 (2019) es la versión principal actual con compatibilidad retrospectiva con RxJava 2.
La idea central de RxJava es que todo es un flujo: flujo de datos, flujo de eventos, flujo de estados. Cualquier operación asíncrona puede representarse como un Observable que emite datos, un error o una señal de finalización. Un Observer se suscribe al Observable y recibe notificaciones en tiempo real.
Según Badoo (2024), antes de la transición a corrutinas, el 76% de las aplicaciones Android del top 200 de Google Play usaban RxJava para operaciones asíncronas. La proporción está disminuyendo en favor de las corrutinas, pero RxJava sigue presente en el código de producción de miles de aplicaciones y se considera una tecnología madura y probada. ReactiveX es una especificación multiplataforma implementada también para JavaScript (RxJS), .NET (Rx.NET), Swift (RxSwift) y otros lenguajes.
ReactiveX extiende el patrón Observer clásico con dos mecanismos: encadenamiento de operadores y gestión de hilos mediante Schedulers. Observable no comienza a emitir datos hasta que un Observer se suscribe (evaluación perezosa). Esto permite construir un pipeline de datos que se activa solo cuando existe una suscripción.
Observable — el tipo base que emite 0..N elementos con onError o onComplete. Adecuado para flujos de datos ilimitados — por ejemplo, eventos de clic o actualizaciones de geolocalización. Observable no soporta backpressure.
Flowable — la versión Reactive Streams de Observable con soporte de backpressure. Se usa cuando la fuente de datos puede generar elementos más rápido de lo que el Observer puede procesar. Flowable soporta las estrategias BACKPRESSURE_BUFFER, DROP, LATEST y ERROR.
| Tipo | Elementos | Backpressure | Uso |
|---|---|---|---|
| Observable | 0..N | No | Eventos de UI, flujos pequeños |
| Flowable | 0..N | Sí | Grandes datos, tiempo real |
| Single | 1 (onSuccess/onError) | — | Respuesta única (red) |
| Maybe | 0..1 | — | Valor opcional (caché) |
| Completable | 0 (onComplete/onError) | Operación sin datos (escritura) |
Single emite exactamente un elemento o un error — ideal para peticiones de red. Maybe emite 0 o 1 elemento, adecuado para caché donde los datos pueden no existir. Completable emite solo onComplete u onError, sin datos, conveniente para operaciones de escritura o eliminación. Estos tipos simplifican la API al reducir el contrato a un caso específico. Retrofit (un popular cliente HTTP para Android) soporta directamente los cinco tipos de RxJava, permitiendo elegir el tipo de retorno más apropiado para cada endpoint sin código repetitivo adicional.
Los operadores son funciones que transforman un Observable en otro. Una cadena de operadores describe el pipeline de datos: cada operador toma el flujo del anterior, lo transforma y lo pasa al siguiente. RxJava contiene más de 200 operadores agrupados en categorías.
flatMap es uno de los operadores más potentes de RxJava. Permite ejecutar una petición asíncrona para cada elemento y recoger los resultados en un flujo común. Por ejemplo, flatMap se usa para cargar detalles a partir de una lista de IDs: cada ID → petición de red → fusión de resultados. A diferencia de map, que simplemente transforma un elemento, flatMap puede emitir múltiples elementos o cambiar a otro Observable, lo que lo convierte en la base para construir pipelines asíncronos.
onErrorResumeNext — cambia a un Observable de respaldo en caso de error. retry — reintenta la suscripción N veces al ocurrir un error. onErrorReturn — devuelve un valor por defecto en lugar del error. doOnError — realiza una acción secundaria al ocurrir un error sin modificar el flujo (registro o análisis). La combinación de estos operadores permite construir pipelines robustos con una estrategia clara de manejo de errores sin try/catch manual.
Los Schedulers determinan en qué hilo se ejecutan Observable y Observer. subscribeOn establece el hilo para la fuente, observeOn establece el hilo para el Observer y los operadores posteriores. Esta separación es una ventaja clave de RxJava: fuente en hilo IO, procesamiento en computation, UI en el hilo principal.
Principales Schedulers: Schedulers.io() — para operaciones de E/S (red, disco), pool ilimitado. Schedulers.computation() — para cálculos, pool fijo según el número de núcleos. Schedulers.newThread() — un nuevo hilo para cada tarea. AndroidSchedulers.mainThread() — hilo principal de Android (RxAndroid). También existe Schedulers.trampoline() para ejecutar tareas en el hilo actual con una cola FIFO, útil para pruebas.
Según Google (2025), el uso correcto de los Schedulers es la parte más difícil de RxJava para principiantes. Un error típico es llamar a subscribeOn después de observeOn, lo que no afecta a la fuente. subscribeOn debe ser el primero en la cadena para la fuente, observeOn antes de la suscripción UI. Regla: subscribeOn solo afecta al upstream (fuente), observeOn cambia el downstream (suscriptor y todos los operadores posteriores).
Consideremos tres escenarios: una petición de red con Single, peticiones paralelas con zip y debounce para un campo de búsqueda con debounce.
Single es perfecto para peticiones Retrofit: una petición — una respuesta. Suscríbete en el hilo principal para actualizaciones de UI.
api.getUser(id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<User>() {
@Override
public void onSuccess(User user) { showUser(user); }
@Override
public void onError(Throwable e) { showError(e); }
})
zip combina los resultados de dos Singles independientes en uno. Se ejecutan en paralelo, el resultado se produce después de que ambos finalicen.
Single.zip(
api.getProfile(),
api.getSettings(),
(profile, settings) -> new Dashboard(profile, settings)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(dashboard -> showDashboard(dashboard), e -> logError(e))
debounce ignora cambios rápidos de texto y envía una petición solo después de una pausa de 400 ms. distinctUntilChanged cancela la petición si el texto no ha cambiado.
RxTextView.textChanges(searchView)
.debounce(400, TimeUnit.MILLISECONDS)
.filter(text -> text.length() >= 3)
.distinctUntilChanged()
.switchMap(query -> api.search(query))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(results -> showResults(results))
RxJava y Kotlin Coroutines resuelven el mismo problema — programación asíncrona — pero con enfoques fundamentalmente diferentes. RxJava está basado en el patrón Observer y es push-based: la fuente envía datos, el Observer reacciona. Las corrutinas son pull-based: el código solicita datos secuencialmente mediante await.
Según Google I/O 2024, Kotlin Coroutines es el enfoque recomendado para nuevo código asíncrono en Android. RxJava sigue siendo compatible para proyectos existentes. Google proporciona bibliotecas de puente (kotlinx-coroutines-rx3) para una migración gradual. AndroidX (LiveData, Room, Paging 3) soporta ambos enfoques, permitiendo usar RxJava en módulos antiguos y corrutinas en los nuevos sin conflictos de dependencias.
Transición gradual: cada nuevo componente se escribe con corrutinas, el código RxJava antiguo no se modifica. RxJava → corrutinas mediante awaitSingle() o awaitFirst(). Corrutinas → RxJava mediante future() o asFlowable(). La migración completa lleva de 6 a 18 meses para proyectos grandes.
Preguntas frecuentes
Observable no soporta backpressure — si la fuente genera datos más rápido de lo que el manejador los procesa, se produce una MissingBackpressureException. Flowable soporta backpressure de Reactive Streams con estrategias de búfer configurables.
subscribeOn establece el Scheduler para ejecutar el Observable fuente. observeOn establece el Scheduler para el Observer y todos los operadores posteriores en la cadena. subscribeOn afecta al upstream, observeOn al downstream.
Para proyectos nuevos — sí, Google recomienda corrutinas. Para proyectos existentes — migración gradual mediante kotlinx-coroutines-rx3. RxJava sigue siendo estable y compatible para código heredado.
Mediante operadores: onErrorReturn (valor por defecto), onErrorResumeNext (Observable de respaldo), retry (reintentar N veces). O mediante Observer.onError() para mostrar al usuario.
CompositeDisposable es un contenedor para gestionar múltiples suscripciones. Al llamar a dispose(), se cancelan todas las suscripciones añadidas. Se usa en Activity/Fragment para cancelar todas las peticiones al destruir la pantalla.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también