¿Debo cancelar la suscripción al utilizar rxbinding?

Hay cómo uso RxBinding con Kotlin:

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) reset_password_text_view.clicks().subscribe { presenter.showConfirmSecretQuestionBeforeResetPassword() } password_edit_text.textChanges().skip(1).subscribe { presenter.onPasswordChanged(it.toString()) } password_edit_text.editorActionEvents().subscribe { presenter.done(password_edit_text.text.toString()) } } 

Observable.subscribe(action) devuelve la Subscription . ¿Debo mantenerlo como referencia y onPause() suscripción onPause() o onDestroy() ?

Me gusta esto:

 private lateinit var resetPasswordClicksSubs: Subscription override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) resetPasswordClicksSubs = reset_password_text_view.clicks().subscribe { presenter.showConfirmSecretQuestionBeforeResetPassword() } } override fun onDestroy() { super.onDestroy() resetPasswordClicksSubs.unsubscribe() } 

He hecho una pequeña configuración de prueba para averiguarlo. No es una aplicación para Android, sino que simula las relaciones de clase. Esto es lo que parece:

 class Context class View(val context: Context) { lateinit var listener: () -> Unit fun onClick() = listener.invoke() } fun View.clicks() = Observable.fromEmitter<String>({ emitter -> listener = { emitter.onNext("Click") } }, Emitter.BackpressureMode.DROP) var ref: PhantomReference<Context>? = null fun main(args: Array<String>) { var c: Context? = Context() var view: View? = View(c!!) view!!.clicks().subscribe(::println) view.onClick() view = null val queue = ReferenceQueue<Context>() ref = PhantomReference(c, queue) c = null val t = thread { while (queue.remove(1000) == null) System.gc() } t.join() println("Collected") } 

En este fragmento instancio una View que contiene una referencia a un Context . la vista tiene una devolución de llamada para los eventos de clic que envuelvo en un Observable . Activar la devolución de llamada una vez, luego PhantomReference todas las referencias a la View y el Context y sólo mantener una PhantomReference . A continuación, en un hilo independiente espero hasta que se publique la instancia de Context . Como puede ver, nunca me desinscribo del Observable .

Si ejecuta el código, se imprimirá

Hacer clic

Recogido

y luego terminan probando que la referencia al Context fue efectivamente liberada.


Lo que esto significa para ti

Como puede ver, un Observable no impedirá que los objetos referenciados se recojan si las únicas referencias que tiene a él son circulares. Puede leer más sobre referencias circulares en esta pregunta .

Sin embargo, no siempre es así. Dependiendo de los operadores que utilice en la cadena observable, la referencia se puede filtrar, por ejemplo, por un programador o si se fusiona con un observable infinito, como interval() . Explicarly unsubscribing de un observable es siempre una buena idea y usted puede reducir el boilerplate necesario usando algo como RxLifecycle .

Creo que Jake Wharton (el creador de la biblioteca) dio la mejor respuesta :

Trate a un RxView.clicks suscripto () (o cualquier observable de esta biblioteca para esa materia) como usted haría la referencia de la visión sí mismo. Si lo pasa (o se suscribe a él) en algún lugar fuera de la vida útil de la vista, acaba de filtrar toda su actividad.

Por lo tanto, si acaba de suscribirse dentro de su ViewHolder no hay necesidad de darse de baja como si no hubiera necesidad de anular el registro de un oyente de clics si lo hacía manualmente.

Sí, si miras en el doc , dice explícitamente:

  • Advertencia: El observable creado mantiene una referencia fuerte a la view . Anular la suscripción para liberar esta referencia.

Sí, debe darse de baja al utilizar RxBinding .

Aquí hay una forma … (en java, podría ser modificado para kotlin?)

Recoger

Dentro de su Actividad o Fragmento, agregue desechables a un CompositeDisposable que dispondrá en onDestroy ().

 CompositeDisposable mCompD; // collector Disposable d = RxView.clicks(mButton).subscribe(new Consumer...); addToDisposables(mCompD, d); // add to collector public static void addToDisposables(CompositeDisposable compDisp, Disposable d) { if (compDisp == null) { compDisp = new CompositeDisposable(); } compDisp.add(d); } 

Disponer

 @Override protected void onDestroy() { mCompD.dispose(); super.onDestroy(); } 
  • RxAndroid: ¿cuándo usar bindActivity y por qué?
  • Prueba de RxBinding RxSearchView
  • CalledFromWrongThreadException incluso cuando se utiliza AndroidSchedulers.mainThread ()
  • RxJava2 en la función de devolución de llamada onLoadFinished de CursorLoader
  • Comportamiento de onNext y onComplete
  • Retrofit con rxjava manejando excepciones de red a nivel mundial
  • Solución global de errorHandling con RxJava sólo cuando onError no está implementado
  • Limitar el rendimiento con RxJava
  • Solo observable con varios suscriptores
  • Flatten Observable <Observable <Cursor >> Observable <Cursor>
  • Rx Java mergeDelayError no funciona como se esperaba
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.