У меня есть Activity, который создает экземпляр Presenter. На уровне Presenter я получаю экземпляр Observable из репозитория. Затем я подписываюсь на Observable с помощью подкласса Subscriber, а затем добавляю полученный объект Subscription к CompositeSubscription. Поскольку мне нужно изменить действие, как только вызываемый подписчик onNext() был вызван, я также передаю ссылку Presenter подписчику.Android, RxJava, MVP и утечки памяти
Теперь мне интересно, как работают ссылки и что становится пригодным для сбора мусора и когда.
Пример 1: Наблюдение подписчивается с использованием Абонента, и Подписка добавляется в Композитную подписку. До того, как вызов onNext() абонента может быть вызван, родительская активность вызывает событие onPause() lifecycle. Он сообщает ведущему о том, что он нажимает onPause(), и Presenter вызывает clear() в CompositeSubscription.
На данный момент есть подпись CompositeSubscription, Subscriber и Observable для GC? Или в методе onPause() в Presenter мне нужно явно обнулить ссылки на Observable, Subscriber и CompositeSubscription?
Пример 2:
Аналогично примеру 1 презентатор подписывается на наблюдаемом и до того, как метод onNext() Абонента называется активность проходит через OnPause(), но на этот раз она также проходит через onResume().
Как и в примере 1, Ведущий вызывает clear() в CompositeSubscription в onPause().
Затем в onResume происходит следующее: Ведущий ранее кэшировал Observable в одноэлементном классе, поэтому в onResume он может видеть, что в кэше есть Observable, означающий, что Observable никогда не заканчивается. Итак, Presenter теперь создает новый экземпляр Subscriber и новый экземпляр CompositeSubscription и подписывается на кешированный Observable, используя новые экземпляры Subscriber и CompositeSubscription.
Но теперь мой вопрос: я представил утечку памяти? Первый экземпляр подписчика имеет ссылку на Presenter. Когда вызывается onResume(), я создаю второй экземпляр Subscriber, а Presenter ссылается на этот новый экземпляр. Итак, что происходит с первым экземпляром подписчика? Является ли он подходящим для GC или создает утечку памяти, потому что он ссылается на презентатора, но больше не ссылается на него?
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);
}
}
Мое главное повесить здесь было дерево ссылок и не понимать, как сборщик мусора обходит дерево, когда он определяет, имеет ли что-то право на GC или нет. Ваш ответ правильный. – neonDion