I have a Fragment A
that uses Retrofit to calls an API in onCreateView
.
The result will be used to display a list of objects.
Fragment A
also has a button which navigates to Fragment B
, by commiting a FragmentTransaction
and replace itself. (Fragment A
onDestroyView
triggered)
Everything works well, but when I back from Fragment B
to Fragment A
(Fragment A
onCreateView
triggered), API is not called.
This only happens if I call Disposable.dispose()
in onDestroyView
, which is an attempt to prevent memory leaks.
Since new Observable
s will be created every time onCreateView
is triggered, they are supposed to be indenpendent of the previously disposed Disposables
. And therefore API will be called again and callbacks will be triggered. The list of object should be refreshed.
onCreateView
is triggered, the line which tells Retrofit to call API is also triggered. But none of the callbacks (including .map()
) are triggered. Since I have also logged network traffics, I am pretty sure that no network communication has actually been made. It looks like either RxJava or Retrofit decided to stop the stream.
Of course this can be avoided if I do not use Disposable.dispose()
. But I do want to prevent memory leaks.
What is the correct way to do this?
Fragment 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();
}
}
Most Importantly, APIResponseObserver
which does the job of adding the disposable:
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() {
//...
}
}
I have also tried to use RxLifecycle, but produced the same result.
Just found out that I should have used Disposable.clear()
instead of dispose()
. dispose()
made me no longer be able to add Disposable
to the same CompositeDisposable
.
An interesting fact is, RxLifecycle produces the same problem. Does it mean they use dispose()
instead of clear()
?
For RxLifecycle, you may refer to this Github issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With