I am using CursorLoader to load data from database inside my Fragment, which has a RecyclerView. This fragment is being used inside a ViewPager. The ViewPager is contained inside a ContainerFragment, which in turn is inside an Activity.
The ContainerFragment initializes first 4 loaders out of the 10 required in onActivityCreated()
. From the log I can see that the loader(s) are in fact getting created. However, onLoadFinished
is not getting called for any of the loaders.
Now the twist comes when I swipe through the ViewPager to the third fragment. Now I see the third loader's onLoadFinished
getting called. Now this is probably not called from the fragment but from the PagerAdapter's getItem()
method, which in addition to instantiating the fragments, also initializes loaders with their IDs in case they haven't been already.
From all other questions on StackOverflow about onLoadFinished not getting called, I have tried the following solutions which are not working for me:
- Using
forceLoad()
this.getListView().refreshDrawableState();
-> not tried, and don't understand why this should work. Moreover, I am using RecyclerView.- "Importing the correct class" -> I am using AndroidX, and moreover, the loader does load sometimes. If it was the wrong class, it wouldn't have worked any time right?
- "Fragment should use
SupportLoaderManager
" -> tried replacing in the fragment withgetActivity().getSupportLoaderManager
. For fragment I think it's justgetLoaderManager
. It was already working sometimes with justgetLoaderManager
. (No difference observed)
#onActivityCreated
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
startLoaders();
}
startLoaders()
private void startLoaders() {
while(loaderSeqIndex < CATEGORIES.size() && loaderSeqIndex < 4) {
Bundle bundle = new Bundle();
bundle.putString("category", CATEGORIES.get(loaderSeqIndex));
getLoaderManager().initLoader(loaderSeqIndex++, bundle, this);
}
}
LoaderCallbacks
@NonNull
@Override
public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
Timber.i("Loader created onCreateLoader called");
CursorLoader loader = ArticleLoader.newCategorizedArticlesInstance(getContext(), args.getString("category"));
loader.registerListener(id, new Loader.OnLoadCompleteListener<Cursor>() {
@Override
public void onLoadComplete(Loader<Cursor> loader, Cursor data) {
int position = loader.getId();
cursorHashMap.put(CATEGORIES.get(position), data);
Timber.i("mPager.getCurrentItem(): " + mPager.getCurrentItem() + " position: " + position);
if (position == mPager.getCurrentItem()) {
ArticleListViewModel model = ViewModelProviders.of(ArticleListContainerFragment.this).get(ArticleListViewModel.class);
model.setCursor(data);
}
}
});
return loader;
}
@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
int position = loader.getId();
cursorHashMap.put(CATEGORIES.get(position), data);
Timber.i("mPager.getCurrentItem(): " + mPager.getCurrentItem() + " position: " + position);
if(position == mPager.getCurrentItem()) {
ArticleListViewModel model = ViewModelProviders.of(this).get(ArticleListViewModel.class);
model.setCursor(data);
// mPagerAdapter.notifyDataSetChanged();
}
}
PagerAdapter's #getView
private class MyPagerAdapter extends FragmentStatePagerAdapter {
...
@Override
public Fragment getItem(int position) {
ArticleListFragment fragment = ArticleListFragment.newInstance();
Bundle bundle = new Bundle();
bundle.putString("category", CATEGORIES.get(position));
bundle.putInt("id",position);
fragment.setArguments(bundle);
// fragment.setCursor(cursorHashMap.get(CATEGORIES.get(position)));
return fragment;
}
...
}
I was expecting timber to print from the #onLoadFinished
method just to make sure that it's getting called, which isn't happening.
Something weird that is happening is that:
the cursorHashMap
that I am using, get's properly populated I open the app a second time (when refresh doesn't happen). And the cursor get's populated without #onLoadFinished
being called.