我是否必须取消订阅已完成的可观察对象?
Do I have to unsubscribe from completed observable?
如果一个 observable 完成,我是否仍然需要取消订阅/处置(在 RxJava2 中)该 observable 以删除 Observer(防止内存泄漏),或者这是否由 RxJava 在 onComplete
或 onError
事件发生?
其他类型如 Single
、Completable
、Flowable
等
是的,你是对的。
流终止后(已调用 onComplete / onError),订阅者自动取消订阅。您应该能够在订阅对象上使用 isUnsubscribed()
方法测试这些行为。
虽然您不需要手动取消订阅已终止的流,但如果您不小心,仍然可以使用 RxJava2 造成内存泄漏。
考虑以下代码:
repository.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> myTextView.setText(data.toString()));
订阅中的 lambda 参数是 "syntatic sugar" 匿名内部 class:
subscribe(new Consumer<Data>() {
@Override
public void accept(final Data data) {
myTextView.setText(data.toString());
}
});
在 JVM 上,匿名内部 class 维护对外部 class 的引用。
假设对于上面的天真代码,外部 class 是一个 Activity(这也适用于 Fragment、Service、BroadcastReceiver 或任何生命周期受控的 class由 Android OS)。
Activity 订阅了观察者,但随后在 low-memory 的条件下被 Android OS 销毁(您可以通过打开 Developer Options/Don不保留活动)。如果 Schedulers.io()
上的工作在 Activity 被销毁时仍然是 运行,则仍将通过匿名内部 class 维护对 Activity 的引用。这意味着内存泄漏会阻止 Activity 被垃圾收集器终结。如果 Activity 有多个视图,或者说,一个位图对象,那么内存泄漏可能会非常严重。
这里有很多解决方案,但其中之一是维护一个 CompositeDisposable
对象并在 Android [=40= 的 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的一个很好的例子。
如果一个 observable 完成,我是否仍然需要取消订阅/处置(在 RxJava2 中)该 observable 以删除 Observer(防止内存泄漏),或者这是否由 RxJava 在 onComplete
或 onError
事件发生?
其他类型如 Single
、Completable
、Flowable
等
是的,你是对的。
流终止后(已调用 onComplete / onError),订阅者自动取消订阅。您应该能够在订阅对象上使用 isUnsubscribed()
方法测试这些行为。
虽然您不需要手动取消订阅已终止的流,但如果您不小心,仍然可以使用 RxJava2 造成内存泄漏。
考虑以下代码:
repository.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> myTextView.setText(data.toString()));
订阅中的 lambda 参数是 "syntatic sugar" 匿名内部 class:
subscribe(new Consumer<Data>() {
@Override
public void accept(final Data data) {
myTextView.setText(data.toString());
}
});
在 JVM 上,匿名内部 class 维护对外部 class 的引用。
假设对于上面的天真代码,外部 class 是一个 Activity(这也适用于 Fragment、Service、BroadcastReceiver 或任何生命周期受控的 class由 Android OS)。
Activity 订阅了观察者,但随后在 low-memory 的条件下被 Android OS 销毁(您可以通过打开 Developer Options/Don不保留活动)。如果 Schedulers.io()
上的工作在 Activity 被销毁时仍然是 运行,则仍将通过匿名内部 class 维护对 Activity 的引用。这意味着内存泄漏会阻止 Activity 被垃圾收集器终结。如果 Activity 有多个视图,或者说,一个位图对象,那么内存泄漏可能会非常严重。
这里有很多解决方案,但其中之一是维护一个 CompositeDisposable
对象并在 Android [=40= 的 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的一个很好的例子。