我必须取消订阅已完成的可观察对象吗?

2022-09-01 06:49:16

如果可观察量完成,我是否仍必须取消订阅/释放(在RxJava2中)可观察量以删除观察者(防止内存泄漏),或者一旦发生或事件,RxJava是否在内部处理?onCompleteonError

那么其他类型呢,如 、 等。SingleCompletableFlowable


答案 1

是的,你是对的。

流终止后(已调用“完成”/“打开错误”),订阅者将自动取消订阅。您应该能够在订阅对象上使用方法测试这些行为。isUnsubscribed()


答案 2

虽然您不需要手动取消订阅已终止的流,但如果不小心,您仍然可以使用 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 上,匿名内部类维护对外部类的引用。

假设对于上述朴素代码,外部类是一个活动(对于片段,服务,BroadcastReceiver或任何生命周期由Android操作系统控制的类也是如此)。

活动订阅观察者,但在内存不足的情况下被 Android 操作系统销毁(您可以通过打开开发人员选项/不保留活动来模拟此效果)。如果在销毁活动时,上的工作仍在运行,则仍将通过匿名内部类维护对活动的引用。这意味着内存泄漏,阻止垃圾回收器最终确定活动。如果活动具有多个视图,或者说,具有一个位图对象,则内存泄漏可能非常严重。Schedulers.io()

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

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的好例子。


推荐