我必须取消订阅已完成的可观察对象吗?
如果可观察量完成,我是否仍必须取消订阅/释放(在RxJava2中)可观察量以删除观察者(防止内存泄漏),或者一旦发生或事件,RxJava是否在内部处理?onComplete
onError
那么其他类型呢,如 、 等。Single
Completable
Flowable
如果可观察量完成,我是否仍必须取消订阅/释放(在RxJava2中)可观察量以删除观察者(防止内存泄漏),或者一旦发生或事件,RxJava是否在内部处理?onComplete
onError
那么其他类型呢,如 、 等。Single
Completable
Flowable
是的,你是对的。
流终止后(已调用“完成”/“打开错误”),订阅者将自动取消订阅。您应该能够在订阅对象上使用方法测试这些行为。isUnsubscribed()
虽然您不需要手动取消订阅已终止的流,但如果不小心,您仍然可以使用 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的生命周期方法中清除它:CompositeDisposable
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的好例子。