【发布时间】:2017-01-11 19:10:54
【问题描述】:
我有一个创建 Presenter 实例的 Activity。在 Presenter 层中,我从存储库中获取了一个 Observable 的实例。然后我使用订阅者的子类订阅 Observable,然后将生成的订阅对象添加到 CompositeSubscription。因为我需要在调用订阅者的 onNext() 后修改活动,所以我还将 Presenter 的引用传递给订阅者。
现在我想知道引用是如何工作的,什么时候可以进行垃圾回收。
示例 1: Observable 使用订阅者订阅,订阅被添加到 CompositeSubscription。在调用订阅者的 onNext() 之前,父活动会触发其 onPause() 生命周期事件。它告诉 Presenter 点击 onPause() 并且 Presenter 在 CompositeSubscription 上调用 clear()。
此时 CompositeSubscription、Subscriber 和 Observable 是否符合 GC 条件?或者在 Presenter 的 onPause() 方法中,我是否需要显式地清空对 Observable、Subscriber 和 CompositeSubscription 的引用?
示例 2:
与示例 1 类似,Presenter 订阅了一个 Observable,并且在调用 Subscriber 的 onNext() 方法之前,Activity 会执行 onPause(),但这次它也会执行 onResume()。
就像在示例 1 中一样,Presenter 在 onPause() 中对 CompositeSubscription 调用 clear()。
然后在 onResume 中会发生以下情况: Presenter 之前将 Observable 缓存在一个单例类中,因此在 onResume 中它可以看到缓存中有一个 Observable,这意味着 Observable 从未完成运行。因此,Presenter 现在创建了一个新的 Subscriber 实例和一个新的 CompositeSubscription 实例,并使用新的 Subscriber 和 CompositeSubscription 实例订阅缓存的 Observable。
但现在我的问题是,我是否引入了内存泄漏? Subscriber 的第一个实例引用了 Presenter。当 onResume() 被调用时,我创建了 Subscriber 的第二个实例,Presenter 引用了这个新实例。那么订阅者的第一个实例会发生什么?它是否符合 GC 条件,还是因为它引用了 Presenter 但不再有指向它的引用而造成内存泄漏?
class Presenter {
private MyActivity mActivity;
private Repository mRepository;
private GlobalCache mGlobalCache;
private CompositeSubscription mCompSub;
public Presenter(MyActivity activity, Repository repository, GlobalCache globalCache) {
mActivity = activity;
mRepository = repository;
mGlobalCache = globalCache;
}
public void doLongRunningThing() {
Observable<Object> obs = mRepository.getObs();
mGlobalCache.retain(obs);
mCompSub = new CompositeSubscription();
MySubscriber subscriber = new Subscriber(this);
compSub.add(obs.subscribe(subscriber));
}
public void onResume() {
if (mGlobalCache.getObs() != null) {
Observable<Object> obs = mGlobalCache.getObs();
mCompSub = new CompositeSubscription();
MySubscriber subscriber = new Subscriber(this);
compSub.add(obs.subscribe(subscriber));
}
}
public void onPause() {
if(mCompSub != null && mCompSub.hasSubscriptions()) {
mCompSub.clear();
}
}
public void onDestroy() {
mActivity = null;
mRepository = null;
mGlobalCache = null;
}
public void handleResponse(Object object) {
activity.setUiToSomeState();
}
}
class MySubscriber extends Subscriber<Object> {
private Presenter mPresenter;
private GlobalCached mGlobalCache;
public MySubscriber(Presenter presenter, GlobalCache globalCache) {
mPresenter = presenter;
mGlobalCache = globalCache;
}
onCompleted() {
}
onError() {
}
onNext(Object object) {
mGlobalCache.clearObs();
mPresenter.handleResponse(object);
}
}
【问题讨论】:
标签: android memory-leaks rx-java