rxjava rxandroid kotlin rx-kotlin

kotlin - rxandroid - rxjava



¿Cómo las corutinas de Kotlin son mejores que RxKotlin? (3)

¿Por qué querría usar las corutinas de Kotlin?

Parece que la biblioteca RxKotlin es mucho más versátil. Las corutinas de Kotlin se ven significativamente menos potentes y más engorrosas de usar en comparación.

Baso mi opinión en las rutinas en esta charla de diseño de Andrey Breslav (JetBrains): https://www.youtube.com/watch?v=4W3ruTWUhpw

Se puede acceder a la presentación de diapositivas de la conversación aquí: https://www.slideshare.net/abreslav/jvmls-2016-coroutines-in-kotlin

EDITAR (gracias a @hotkey):

Mejor fuente sobre el estado actual de las corutinas: https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md


Hay dos partes en Rx; el patrón Observable y un conjunto sólido de operadores para manipularlos, transformarlos y combinarlos. El patrón Observable, por sí solo, no hace mucho. Lo mismo con las corutinas; Es solo otro paradigma para lidiar con el asincronismo. Puede comparar las ventajas y desventajas de las devoluciones de llamada, Observable y corutinas para resolver un problema determinado, pero no puede comparar un paradigma con una biblioteca con todas las funciones. Es como comparar un lenguaje con un marco.

¿Cómo las corutinas de Kotlin son mejores que RxKotlin? Todavía no usé corutinas, pero es similar a async / wait en C #. Simplemente escribe código secuencial, todo es tan fácil como escribir código síncrono ... excepto que se ejecuta de forma asíncrona. Es más fácil de entender.

¿Por qué querría usar las corutinas de Kotlin? Contestaré por mí mismo. La mayoría de las veces me apegaré a Rx, porque estoy a favor de la arquitectura basada en eventos. Pero si surge la situación en la que estoy escribiendo código secuencial, y necesito llamar a un método asincrónico en el medio, felizmente aprovecharé las rutinas para mantenerlo así y evitaré envolver todo en Observable.

Editar : ahora que estoy usando corutinas, es hora de una actualización.

RxKotlin es solo azúcar sintáctico para usar RxJava en Kotlin, así que hablaré sobre RxJava y no sobre RxKotlin a continuación. Las corutinas son una palanca más baja y un concepto más general que RxJava, sirven a otros casos de uso. Dicho esto, hay un caso de uso en el que podrías comparar RxJava y las corutinas ( channel ), es transmitir datos de forma asincrónica. Las corutinas tienen una clara ventaja sobre RxJava aquí:

Las corutinas son mejores para lidiar con los recursos

  • En RxJava puede asignar cálculos a planificadores, pero subscribeOn() y ObserveOn() son confusos. Cada rutina tiene un contexto de hilo y vuelve al contexto padre. Para un canal, ambos lados (productor, consumidor) se ejecutan en su propio contexto. Las rutinas son más intuitivas en la afectación de hilos o grupos de hilos.
  • Las rutinas dan más control sobre cuándo ocurren esos cálculos. Puede, por ejemplo, pasar la mano ( yield ), priorizar ( select ), paralelizar ( producer / actor múltiple en el channel ) o bloquear el recurso ( Mutex ) para un cálculo dado. Puede que no importe en el servidor (donde RxJava vino primero) pero en un entorno de recursos limitados, este nivel de control puede ser requerido.
  • Debido a su naturaleza reactiva, la contrapresión no se ajusta bien en RxJava. En el otro extremo, send() to channel es una función suspensiva que se suspende cuando se alcanza la capacidad del canal. Es una contrapresión lista para usar dada por la naturaleza. También puede offer() al canal, en cuyo caso la llamada nunca se suspende, pero devuelve false en caso de que el canal esté lleno, reproduciendo efectivamente onBackpressureDrop() de RxJava. O simplemente podría escribir su propia lógica de contrapresión personalizada, que no será difícil con las rutinas, especialmente en comparación con RxJava.

Hay otro caso de uso, donde las corutinas brillan y esto responderá a su segunda pregunta "¿Por qué querría usar las corutinas de Kotlin?". Las rutinas son el reemplazo perfecto para hilos de fondo o AsyncTask (Android). Es tan fácil como launch { someBlockingFunction() } . Por supuesto, también puede lograr esto con RxJava, utilizando tal vez Schedulers y Completable . No usará (o poco) el patrón Observador y los operadores que son la firma de RxJava, una pista de que este trabajo está fuera del alcance de RxJava. La complejidad de RxJava (un impuesto inútil aquí) hará que su código sea más detallado y menos limpio que la versión de Coroutine.

La legibilidad importa. En este sentido, el enfoque de RxJava y las corutinas difieren mucho. Las corutinas son más simples que RxJava. Si no está a gusto con map() , flatmap() y la programación funcional reactiva en general, las manipulaciones de las rutinas son más fáciles e incluyen instrucciones básicas: for , if , try/catch ... Pero personalmente encuentro que el código de la rutina es más difícil de entender para tareas no triviales. Especialmente implica más anidamiento e indentación, mientras que el encadenamiento del operador en RxJava mantiene todo en línea. La programación de estilo funcional hace que el procesamiento sea más explícito. Además de eso, RxJava puede resolver transformaciones complejas con unos pocos operadores estándar de su conjunto de operadores rico (OK, demasiado rico). RxJava brilla cuando tiene flujos de datos complejos que requieren muchas combinaciones y transformaciones.

Espero que esas consideraciones lo ayuden a elegir la herramienta adecuada para sus necesidades.


La conversación / documento que vinculó no habla de canales. Los canales son los que llenan el vacío entre su comprensión actual de las rutinas y la programación basada en eventos.

Con las rutinas y los canales, puede hacer una programación controlada por eventos como probablemente esté acostumbrado a hacer con rx, pero puede hacerlo con código de aspecto sincrónico y sin tantos operadores "personalizados".

Si desea comprender esto mejor, le sugiero que mire fuera de Kotlin, donde esos conceptos son más maduros y refinados (no experimentales). Mire core.async de Clojure, videos de Rich Hickey, publicaciones y discusiones relacionadas.


Las corutinas de Kotlin son diferentes de Rx. Es difícil compararlas manzanas con manzanas, porque las corutinas de Kotlin son una característica de lenguaje delgado (con solo un par de conceptos básicos y algunas funciones básicas para manipularlas), mientras que Rx es una biblioteca bastante pesada con una gran variedad de operadores listos para usar. Ambos están diseñados para abordar un problema de programación asincrónica, sin embargo, su enfoque para la solución es muy diferente:

  • Rx viene con un estilo funcional particular de programación que se puede implementar en prácticamente cualquier lenguaje de programación sin el soporte del lenguaje mismo. Funciona bien cuando el problema en cuestión se descompone fácilmente en una secuencia de operadores estándar y, de lo contrario, no es tan bueno.

  • Las rutinas de Kotlin proporcionan una función de lenguaje que permite a los escritores de bibliotecas implementar varios estilos de programación asincrónica, que incluyen, entre otros, el estilo reactivo funcional (Rx). Con las rutinas de Kotlin también puede escribir su código asincrónico en un estilo imperativo, en un estilo basado en promesas / futuros, en un estilo de actor, etc.

Es más apropiado comparar Rx con algunas bibliotecas específicas que se implementan en base a las rutinas de Kotlin.

Tome la biblioteca kotlinx.coroutines como un ejemplo. Esta biblioteca proporciona un conjunto de primitivas como async/await y canales que normalmente se integran en otros lenguajes de programación. También tiene soporte para actores livianos sin futuro. Puede leer más en la Guía de kotlinx.coroutines por ejemplo .

Los canales proporcionados por kotlinx.coroutines pueden reemplazar o aumentar Rx en ciertos casos de uso. Hay una guía separada para flujos reactivos con corutinas que profundiza en las similitudes y diferencias con Rx.