Retrofit + RxJava - 如果我使用了Disposable.dispose()

时间:2018-04-16 07:09:56

标签: android android-fragments retrofit rx-java2

我有Fragment A使用Retrofit来调用onCreateView中的API 结果将用于显示对象列表。

Fragment A还有一个导航到Fragment B的按钮,通过提交FragmentTransaction并替换自己。 (Fragment A onDestroyView已触发)

一切正常,但当我从Fragment B回到Fragment AFragment A onCreateView已触发)时,API不会被调用。

只有在Disposable.dispose() 中调用onDestroyView时才会发生这种情况,这是为了防止内存泄漏。

我的期望

由于每次触发Observable时都会创建新的onCreateView,因此它们应该与之前处置的Disposables无关。因此将再次调用API并触发回调。应该刷新对象列表。

我观察到的

onCreateView被触发,也会触发告诉Retrofit调用API的行。但是没有一个回调(包括.map())被触发。由于我也记录了网络流量,我很确定实际上没有进行任何网络通信。 看起来RxJava或Retrofit决定停止播放。

问题

当然,如果我不使用Disposable.dispose(),这可以避免。但我确实想防止内存泄漏 这样做的正确方法是什么?

我的代码(简体)

片段A:

public class BeansFragment extends BaseFragment {

   ...

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ...
        retrofit.getSomeBeans()
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new APIResponseObserver<List<Beans>>(this) {
                    @Override
                    public void onNext(List<Beans> beans) {
                        if (getContext() == null) return;
                        setupBeansList(beans);
                    }
                });
        ...
    }

    ...
}

BaseFragment:

public abstract class BaseFragment extends Fragment {

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    ...

    @Override
    public void onDestroyView() {
        compositeDisposable.dispose();
        super.onDestroyView();
    }
}

最重要的是,APIResponseObserver负责添加一次性用品:

public abstract class APIResponseObserver<T> implements io.reactivex.Observer<T> {

    private BaseFragment fragment;

    public APIResponseObserver(BaseFragment fragment) {
        this.fragment = fragment;
    }

    @Override
    public void onSubscribe(Disposable d) {
        if (fragment != null) fragment.addToCompositeDisposable(d);
    }

    @Override
    public void onError(Throwable e) {
        //...
    }

    @Override
    public void onComplete() {
        //...
    }
}

注意

我也试过使用RxLifecycle,但产生了相同的结果。

1 个答案:

答案 0 :(得分:5)

刚刚发现我应该使用Disposable.clear()代替dispose()dispose()让我无法再将Disposable添加到同一CompositeDisposable

一个有趣的事实是,RxLifecycle会产生同样的问题。这是否意味着他们使用dispose()代替clear()

EDIT @二○一八年四月二十○日

对于RxLifecycle,您可以参考this Github issue