35

onComplete如果一个可观察对象完成,我是否仍然需要取消订阅/处置(在 RxJava2 中)可观察对象以删除观察者(防止内存泄漏),或者一旦发生事件或事件,这是否由 RxJava 内部处理onError

其他类型如Single,CompletableFlowable呢?

4

2 回答 2

35

是的,你是对的。

流终止后( onComplete / onError 已被调用),订阅者自动取消订阅。您应该能够使用isUnsubscribed()Subscription 对象上的方法来测试这些行为。

于 2017-01-24T11:19:30.027 回答
15

虽然您不需要手动取消订阅已终止的流,但如果您不小心,仍然可以使用 RxJava2 造成内存泄漏。

考虑以下代码:

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

订阅中的 lambda 参数是匿名内部类的“语法糖”:

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

在 JVM 上,匿名内部类维护对外部类的引用。

假设对于上面的幼稚代码,外部类是一个 Activity(对于 Fragment、Service、BroadcastReceiver 或任何生命周期由 Android 操作系统控制的类也是如此)。

Activity 订阅了 Observer,但随后在内存不足的情况下被 Android OS 销毁(您可以通过打开 Developer Options/Don't Keep Activity 来模拟这种效果)。如果 Activity 销毁时工作Schedulers.io()仍在运行,则仍会通过匿名内部类维护对 Activity 的引用。这意味着内存泄漏会阻止 Activity 被垃圾收集器完成。如果 Activity 有许多视图,或者说,一个 Bitmap 对象,那么内存泄漏可能相当大。

这里有很多解决方案,但其中之一是维护一个对象并在 Android ActivityCompositeDisposable的生命周期方法中清除它:onDestroy()

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

您可以参考官方Google Android Architecture Blueprints中有关如何在 Android 应用程序中使用 RxJava 的一个很好的示例。

于 2018-03-08T08:47:16.440 回答