web-dev-qa-db-fra.com

Quand résilier un abonnement

J'ai une question sur la façon de se désinscrire d'un observable. J'ai deux codes et je ne sais pas vraiment lequel est le meilleur.

Exemple 1 -> Désabonnement de l'abonné une fois le flux terminé:

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
        }
    }

Exemple 2 -> Désabonnement de l'abonnement une fois l'activité détruite:

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();
}

Je dois mentionner que mes observables n'émettront qu'une seule fois, l'activité ne devrait pas attendre plus d'appels de l'Observable.

Quel est le meilleur?

Merci d'avance

29
MarcForn

Parmi les deux options, la deuxième est meilleure.

Dans votre premier exemple, vous êtes unsubscribing dans la méthode onComplete() qui n'est pas nécessaire. Si vous atteignez la onComplete() d'un abonnement, vous n'avez plus la responsabilité de vous en désinscrire.

Votre deuxième exemple est le bon. L'idée derrière le CompositeSubscription est que vous pouvez y ajouter plusieurs Subscriptions puis nettoyer (unsubscribe) à la fois. En d'autres termes, cela vous évite de garder une liste de Subscriptions dont vous devez vous désinscrire.

Une partie délicate de l'utilisation de CompositeSubscription est que si vous l'avez une fois unsubscribe, vous pouvez [~ # ~] pas [~ # ~] réutiliser. Vous pouvez consulter la documentation de la méthode compositeSubscription.add () pour plus de détails. En bref - cela désabonnera directement l'abonnement que vous essayez d'ajouter. Cela a été une décision délibérée (vous pouvez en savoir plus ICI ).

Pour revenir à votre exemple, appeler unsubscribe() dans onDestroy() de l'activité est très bien et vous évitera des fuites de mémoire. En ce qui concerne votre commentaire selon lequel des problèmes se produisent lorsque vous appelez plusieurs fois votre méthode test() - je dirais que votre problème est ailleurs. Peut-être que votre cas d'utilisation ne devrait pas permettre de l'appeler plusieurs fois, peut-être devriez-vous nettoyer les anciennes données avant d'utiliser celles nouvellement reçues, etc. Peut-être que si vous avez expliqué en détail le type de problèmes que vous rencontrez, nous pourrions vous aider davantage. Mais en ce qui concerne le CompositeSubscription - vous l'utilisez et vous vous désabonnez correctement!

28
Vesko

Il n'est pas nécessaire de se désinscrire dans onCompleted. Jetez un oeil à Le contrat observable

Lorsqu'un observable émet une notification OnError ou OnComplete à ses observateurs, cela met fin à l'abonnement. Les observateurs n'ont pas besoin d'émettre une notification de désabonnement pour mettre fin aux abonnements qui sont résiliés par l'Observable de cette manière.

D'un autre côté, vous devez absolument vous désinscrire dans onDestroy afin d'éviter les fuites de mémoire.

28
MyDogTom

Je pense que cela dépend de vos besoins. Si l'activité n'attend pas d'autres appels, je suppose que vous pouvez vous désinscrire à l'intérieur de onCompleted ().

Je me désabonne toujours dans onDestroy ()

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

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

EDIT: jetez un œil à 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();
}
5
Matias Elorriaga