Cuándo cancelar una suscripción


Tengo una pregunta sobre cómo cancelar la suscripción de un observable. Tengo dos códigos y no estoy muy seguro de cuál es mejor.

Ejemplo 1 - > Cancelar la suscripción del suscriptor una vez que la transmisión haya terminado:

Subscriber<String> subscriber = new Subscriber<String>() {
        @Override
        public void onCompleted() {
            progressdialog.dissmiss();
            unsubscribe();
        }

        @Override
        public void onError(Throwable e) {
            progressdialog.dissmiss();
        }

        @Override
        public void onNext(String s) {
            // do something with data
        }
    }

Ejemplo 2 - > Cancelar la suscripción una vez que se destruye la actividad:

private void test(){
    Subscriber<String> subscriber = new Subscriber<String>() {
        @Override
        public void onCompleted() {
            progressdialog.dissmiss();
        }

        @Override
        public void onError(Throwable e) {
            progressdialog.dissmiss();
        }

        @Override
        public void onNext(String s) {
            // do something with data
        }
    };

    subscription = BackendRequest.login(loginRequest)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);

    compositeSubscription.add(subscription);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    this.subscription.unsubscribe();
}

Tengo que mencionar que mis observables solo emitirán una vez, la actividad no debe esperar más llamadas desde el Observable.

Cuál es mejor?

Gracias de antemano

Author: MarcForn, 2016-03-02

3 answers

De las dos opciones, la segunda es mejor.

En tu primer ejemplo estás unsubscribing en el método onComplete() que no es necesario. Si llega al onComplete() de una Suscripción, ya no tiene la responsabilidad de darse de baja de ella.

Su segundo ejemplo es el correcto. La idea detrás de CompositeSubscription es que puede agregar múltiples Subscriptions y luego limpiar (unsubscribe) a la vez. En otras palabras, esto solo te salva de la necesidad de mantener una lista de Subscriptions que necesitas para darse de baja.

Una parte difícil de usar CompositeSubscription es que si lo usas una vez unsubscribe, puedes NO usarlo de nuevo. Puede consultar la documentación de la suscripción a CompositeSubscription.add () método para detalles por qué. En resumen, cancelará directamente la suscripción que está tratando de agregar. Esa ha sido una decisión deliberada (puedes leer más al respecto AQUÍ).

Volviendo a tu ejemplo, llamar a unsubscribe() en onDestroy() de la actividad está bien y guardará usted de fugas de memoria. Con respecto a su comentario de que los problemas ocurren cuando llama a su método test() varias veces, diría que su problema está en otro lugar. Tal vez su caso de uso no debería permitir llamarlo varias veces, tal vez debería limpiar los datos antiguos antes de usar el recién recibido, etc. Tal vez si usted ha explicado en detalle a qué tipo de problemas se enfrenta podríamos ayudar más. Pero en lo que respecta a CompositeSubscription, ¡lo está utilizando y cancelando su suscripción correctamente!

 25
Author: Vesko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 22:43:55

No es necesario darse de baja en onCompleted. Echa un vistazo a El Contrato Observable

Cuando un Observable emite una notificación OnError o onComplete a su observadores, esto termina la suscripción. Los observadores no necesitan emitir una notificación de cancelación de suscripción para finalizar las suscripciones que Observable de esta manera.

Por otro lado, definitivamente debe darse de baja en onDestroy para evitar fugas de memoria.

 26
Author: MyDogTom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 20:18:47

Creo que eso depende de sus necesidades. Si la actividad no espera otras llamadas, supongo que podrías darte de baja dentro de onCompleted ().

Siempre me doy de baja en onDestroy ()

@Override
protected void onDestroy() {
    super.onDestroy();

    if (subscription != null) {
        subscription.unsubscribe();
    }
}

EDITAR: echa un vistazo a http://reactivex.io/RxJava/javadoc/rx/subscriptions/CompositeSubscription.html

private CompositeSubscription mCompositeSubscription = new CompositeSubscription();

private void doSomething() {
    mCompositeSubscription.add(
        AndroidObservable.bindActivity(this, Observable.just("Hello, World!"))
       .subscribe(s -> System.out.println(s)));
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mCompositeSubscription.unsubscribe();
}
 4
Author: Matias Elorriaga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 20:16:48