Do I have to unsubscribe from completed observable?

前端 未结 2 1665
别跟我提以往
别跟我提以往 2021-01-31 17:23

If an observable completes, do I still have to unsubscribe / dispose (in RxJava2) the observable to remove the Observer (prevent memory leaks) or is this handled internally by R

相关标签:
2条回答
  • 2021-01-31 17:45

    While you do not need to manually unsubscribe from a terminated stream, you can still create a memory leak using RxJava2 if you are not careful.

    Consider the following code:

    repository.getData()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(data -> myTextView.setText(data.toString()));
    

    The lambda parameter in the subscribe is "syntatic sugar" over an anonymous inner class:

    subscribe(new Consumer<Data>() {
        @Override
        public void accept(final Data data) {
            myTextView.setText(data.toString());
        }
    });
    

    On the JVM, an anonymous inner class maintains a reference to the outer class.

    Assume that for the above naive code, the outer class is an Activity (this would also follow for a Fragment, Service, BroadcastReceiver or any class whose lifecycle is controlled by the Android OS).

    The Activity subscribes to the Observer but then is destroyed by the Android OS in conditions of low-memory (you can mimic this effect by turning on Developer Options/Don't Keep Activities). If the work on Schedulers.io() is still running when the Activity is destroyed, a reference will still be maintained to the Activity through the anonymous inner class. This means a memory leak that prevents the Activity from being finalized by the garbage collector. If the Activity has a number of Views or, say, a Bitmap object then the memory leak can be quite substantial.

    There are a number of solutions here but one of them is to maintain a CompositeDisposable object and to clear this in the onDestroy() lifecycle method of the Android Activity:

    public class MyActivity extends Activity {
    
       DataRepository dataRepository;
       CompositeDisposable disposables;
    
       @Override
       public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           disposables = new CompositeDisposable();
       }
    
       public void onButtonClick(View v) {
           repository.getData()             
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .doOnSubscribe(disposable -> disposables.add(disposable))
              .subscribe(data -> myTextView.setText(data.toString()));
       }
    
       @Override
       public void onDestroy() {
           disposables.clear();
           super.onDestroy();
       }
    }
    

    You can refer to a good example of how to use RxJava in an Android app in the official Google Android Architecture Blueprints.

    0 讨论(0)
  • 2021-01-31 17:59

    Yes you are correct.

    After a stream is terminated ( onComplete / onError has been called ), subscriber unsubscribes automatically. You should be able to test these behaviors using isUnsubscribed() method on the Subscription object.

    0 讨论(0)
提交回复
热议问题