如果可观察对象完成,我是否仍然必须取消订阅/处置(在RxJava2中)可观察对象以删除观察者(防止内存泄漏),或者一旦发生on完成
或onError
事件,这是否由RxJava内部处理?
其他类型怎么样,如单
、可完成
、可流动
等。
是的,你是正确的。
终止流后(已调用on完成/onError),订阅者会自动取消订阅。您应该能够在Subscription对象上使用isUn订阅()
方法测试这些行为。
虽然您不需要手动取消订阅已终止的流,但如果不小心,您仍然可以使用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、BroadcastReccher或其生命周期由AndroidOS控制的任何类)。
Activity订阅了观察者,但随后在内存不足的情况下被AndroidOS销毁(您可以通过打开开发人员选项/不保留活动来模拟这种效果)。如果在Activity销毁时Schedulers.io()
上的工作仍在运行,则仍将通过匿名内部类维护对Activity的引用。这意味着内存泄漏会阻止Activity被垃圾收集器最终确定。如果Activity有许多视图,或者说,一个位图对象,那么内存泄漏可能相当大。
这里有许多解决方案,但其中一个是维护一个CompositeDisposable
对象并在Android Activity的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架构蓝图中有关如何在Android应用程序中使用RxJava的一个很好的示例。