Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to unsubscribe a subscription

I have a question regarding how to unsubscribe an observable. I have two codes and I'm not really sure about which one is better.

Example 1 -> Unsubscribe the subscriber once the stream has finished:

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

Example 2 -> Unsubscribe the subscription once the activity is destroyed:

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

I have to mention that my observables only will emit once, the activity should not wait for more calls from the Observable.

Which one is better?

Thanks in advance

like image 884
MarcForn Avatar asked Mar 02 '16 19:03

MarcForn


People also ask

When should I unsubscribe from Observable?

No need to unsubscribe from internal observables of an application scoped service since this service never get's destroyed, unless your entire application get's destroyed, there is no real reason to unsubscribe from it and there is no chance of memory leaks.

Why do we need to unsubscribe from Observable?

In Angular applications, it's always recommended to unsubscribe the observables to gain benefits like: Avoids Memory Leaks. Aborting HTTP requests to avoid unwanted calls.

Do we need to unsubscribe subject?

You always have to unsubscribe from: Any Observable or Subject you created manually.

What happens if you don't unsubscribe from an Observable?

As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak. A memory leak occurs when a section of memory that is no longer being…


3 Answers

From the two options the second one is better.

In your first example you're unsubscribing in the onComplete() method which is not needed. If you reach the onComplete() of a Subscription you don't have the responsibility of unsubscribing from it anymore.

Your second example is the correct one. The idea behind the CompositeSubscription is that you can add multiple Subscriptions to it and then clean up (unsubscribe) at once. In other words this just saves you from the need of keeping a list of Subscriptions that you need to unsubscribe from.

One tricky part using CompositeSubscription is that if you once unsubscribe it, you can NOT use it again. You can check the documentation for the compositeSubscription.add() method for details why. In short - it will directly unsubscribe the Subscription you're trying to add. That's been a deliberate decision (you can read more about it HERE).

Coming back to your example, calling unsubscribe() in onDestroy() of the Activity is fine and will save you from memory leaks. Regarding your comment that problems occur when you call your test() method multiple times - I'd say your problem is somewhere else. Maybe your use-case shouldn't allow to call it multiple times, maybe you should cleanup old data before using the newly received one, etc. Perhaps if you have explained in details what kind of problems you face we could help more. But as far as the CompositeSubscription is concerned - you're using it and unsubscribing from it correctly!

like image 85
Vesko Avatar answered Oct 21 '22 07:10

Vesko


There is no need to unsubscribe in onCompleted. Take a look at The Observable Contract

When an Observable issues an OnError or OnComplete notification to its observers, this ends the subscription. Observers do not need to issue an Unsubscribe notification to end subscriptions that are ended by the Observable in this way.

On the other hand, you definitely should unsubscribe in onDestroy in order to prevent memory leaks.

like image 29
MyDogTom Avatar answered Oct 21 '22 07:10

MyDogTom


I think that depends on your needs. If the activity won't wait for any other calls, I suppose you could unsubscribe inside onCompleted().

I always unsubscribe in onDestroy()

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

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

EDIT: take a look at 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();
}
like image 5
Matias Elorriaga Avatar answered Oct 21 '22 08:10

Matias Elorriaga