如果一个observable完成了,我是否还必须取消订阅/处置(在RxJava2中)observable以删除Observer(防止内存泄漏),或者一旦发生onComplete
或onError
事件发生,这是由RxJava内部处理的吗?
对其他类型的像什么Single
,Completable
,Flowable
等.
是的,你是对的.
流终止后(已调用onComplete/onError),订阅者自动取消订阅.您应该能够使用isUnsubscribed()
Subscription对象上的方法测试这些行为.
虽然您不需要手动取消订阅已终止的流,但如果您不小心,仍可以使用RxJava2创建内存泄漏.
请考虑以下代码:
repository.getData() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(data -> myTextView.setText(data.toString()));
subscribe中的lambda参数是匿名内部类的"syntatic sugar":
subscribe(new Consumer() { @Override public void accept(final Data data) { myTextView.setText(data.toString()); } });
在JVM上,匿名内部类维护对外部类的引用.
假设对于上述天真代码,外部类是一个Activity(这也适用于Fragment,Service,BroadcastReceiver或其生命周期由Android OS控制的任何类).
活动订阅了观察者,但是在内存不足的情况下被Android操作系统销毁(你可以通过打开开发者选项/不要保持活动来模仿这种效果).如果在Schedulers.io()
销毁Activity时仍在运行,则仍将通过匿名内部类向Activity维护引用.这意味着内存泄漏会阻止垃圾收集器完成活动.如果Activity有多个Views或比如Bitmap对象,那么内存泄漏可能非常大.
这里有许多解决方案,但其中一个是维护一个CompositeDisposable
对象并onDestroy()
在Android Activity 的生命周期方法中清除它:
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 .