¿Es mágico RxRelay? Asunto vs RxRelay





En la comunidad de Android, me he encontrado con tres tipos de desarrolladores que se han encontrado con RxRelay:



  1. Aquellos que no entienden por qué se usa RxRelay en su proyecto, por qué es necesario y en qué se diferencia del Subject
  2. Aquellos que piensan que RxRelay "traga" errores o "después de que se ha producido el error RxRelay, seguirá funcionando, pero el Asunto no" (la misma magia)
  3. Aquellos que realmente saben qué es RxRelay.


Si bien los dos primeros tipos son más comunes, decidí escribir un artículo que lo ayudará a comprender cómo funciona RxRelay y comprobar sus propiedades "mágicas".



Si está usando RxJava, probablemente use Subject o RxRelay para lanzar eventos de una entidad a otra o hacer un código reactivo a partir del código imperativo.



Revisemos el punto 2 y veamos cuál es la diferencia entre RxRelay y Subject. Entonces, tenemos dos suscripciones a un relevo, cuando hacemos clic en el botón, empujamos una a este relevo.



class MainActivity : AppCompatActivity() {
   private val relay = PublishRelay.create<Int>()
   private var isError: Boolean = false

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       val disposable1 = relay
           .map {
               if (isError) {
                   isError = false
                   throw Exception()
               } else {
                   isError = true
               }
           }.subscribe(
               {
                   Log.d("test", "  : onNext")
               },
               {
                   Log.d("test", "  : onError")
               }
           )

       val disposable2 = relay
           .subscribe(
               {
                   Log.d("test", "  : onNext")
               },
               {
                   Log.d("test", "  : onError")
               }
           )

       btn.setOnClickListener {
           relay.accept(1)
       }
   }
}


Hacemos clic en el botón tres veces seguidas y vemos dicho registro.

D / prueba: Cadena con error: onNext

D / prueba: Cadena sin error: onNext



D / prueba: Cadena con error: onError

D / prueba: Cadena sin error: onNext



D / prueba: Cadena sin error: onNext



Si reemplaza la variable RxRelay con PublishSubject, el registro no cambiará. He aquí por qué:



en el primer clic, enviamos datos a nuestro relé. Ambos suscriptores se activan.



En el segundo clic de la cadena, el primer suscriptor (desechable1) obtiene un error.



En el tercer clic, el primer desechable1 ya no se dispara, ya que recibió el estado terminal onError. Entonces solo funcionará el segundo desechable2.



Este será el caso de Subject y RxRelay. Permítame recordarle que en rx, los errores bajan por la cadena hasta el suscriptor (aguas abajo) y por encima del lugar donde ocurrieron, no llegan. Terminamos comprobando que el encadenamiento basado en RxRelay no podía funcionar después de que ocurriera un error.



Entonces, si no hay diferencia en el comportamiento de Subject y RxRelay, ¿cuál es su diferencia?



Esto es lo que el propio desarrollador escribe en el archivo README de github:

"Básicamente: un sujeto excepto sin la capacidad de llamar a onComplete u onError".



Es decir, es solo un sujeto sin los métodos onComplete y onError, incluso el código fuente de las clases es casi el mismo. Si llamamos a estos métodos en Subject, dejará de funcionar, ya que recibirá un estado terminal. Por lo tanto, el autor de la biblioteca decidió que valía la pena eliminar estos métodos, porque aquellos desarrolladores que no conocen esta propiedad Subject pueden llamarlos accidentalmente.



Conclusión: la única diferencia entre RxRelay y Subject es la ausencia de dos métodos onComplete y onError, por lo que el desarrollador no puede llamar al estado del terminal.



All Articles