I have fragments making API call via Retrofit
+ RxJava
. I subscribe the Subscription
in onActivityCreated
and dispose at onDestroy
. When I switch from FragmentA
to FragmentB
while FragmentA
is still processing the API call, FragmentB
appears below the content of FragmentA
. It means FragmentA
contents remains on top of the screen and there is no control over it.
FragmentA.java
public class FragmentA extends Fragment {
@BindView(R.id.swipe_refresh) SwipeRefreshLayout mSwipeRefresh;
@BindView(R.id.recycler_view) RecyclerView mRecyclerView;
private ItemsAdapter mAdapter;
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_list, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
ButterKnife.bind(this, view);
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
fetchItems();
}
});
mAdapter = new ItemsAdapter();
mRecyclerView.setAdapter(mAdapter);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mSwipeRefresh.setRefreshing(true);
fetchItems();
}
@Override
public void onDestroy() {
super.onDestroy();
mCompositeDisposable.clear();
}
private void fetchItems() {
RequestInterface requestInterface = Utils.createService();
mCompositeDisposable.add(requestInterface.getItemsForA()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Response>() {
@Override
public void accept(@NonNull Response response) throws Exception {
mAdapter.swapItems(response.getItems());
mSwipeRefresh.setRefreshing(false);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Toast.makeText(getActivity(), "Error: " + throwable.getLocalizedMessage(), Toast.LENGTH_LONG).show();
mSwipeRefresh.setRefreshing(false);
}
}));
}
}
FragmentB.java
public class FragmentB extends Fragment {
//Same as `FragmentA` but different API call
}
I have also did some logging and found out that all of the life-cycle methods for FragmentA
including onDestroyView
gets called.
You need to call following methods on SwipeRefreshLayout
to fix this.
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.destroyDrawingCache();
swipeRefreshLayout.clearAnimation();
super.onDestroyView();
}