I have a fragment in a FragmentPagerAdpater. The Fragment is basically a RecyclerView. The source for the RecyclerView is provided by a Loader which is inside the Fragment.
My problem is that the list appears empty when it is first instantiated. But when I rotate the screen, it appears fine.
Do you have any idea what could go wrong? I am happy to provide some (or a lot) of code if needed. Just tell me which parts you want to see.
Here is the code from the parent activity:
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//We return an instance of the RouteListFragment
RouteListFragment frag = RouteListFragment.getInstance(session.getId());
return frag;
case 1:
//We return an instance of the RouteSpotListFragment
RouteSpotListFragment frag2 = RouteSpotListFragment.getInstance(sessionSpot.getId());
return frag2;
default :
return null;
}
}
The main methods from the Fragment:
public static RouteListFragment getInstance (int sessionId){
RouteListFragment frag = new RouteListFragment();
Bundle bundle = new Bundle ();
bundle.putInt(SESSION_ID, sessionId);
frag.setArguments(bundle);
return frag;
}
/* (non-Javadoc)
* @see android.app.Fragment#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
//We extract the RouteList from the Bundle
Bundle bundle = getArguments();
sessionId = bundle.getInt(SESSION_ID);
//We create a MyRouteListAdapter with a null cursor
Cursor cursor = null;
routeListAdapter = new MyRouteListAdapter(cursor, getActivity());
updateList();
super.onCreate(savedInstanceState);
}
/* (non-Javadoc)
* @see android.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Inflate the layout
layout = (RelativeLayout) inflater.inflate(R.layout.fragment_route_list, container, false);
routeSource = new RouteDataSource (getActivity());
//Now that we have the routeSource, we can prepare the routeListAdapter
routeRecyclerList = (RecyclerView) layout.findViewById(R.id.route_list_view);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(getActivity());
routeRecyclerList.setLayoutManager(mLayoutManager);
routeRecyclerList.setAdapter(routeListAdapter);
return layout;
}
public void updateList(){
/*
* we get the loaderManager to start the query
* If a Loader has already been initiated, we need to reload it. Otherwise the
* onCreateLoader callback method will not be called
* Else, we initiate a Loader
*/
LoaderManager manager = getLoaderManager();
if (manager.getLoader(LOADER_GET_ALL_ROUTES)!= null)
manager.restartLoader(LOADER_GET_ALL_ROUTES, null, this);
else manager.initLoader(LOADER_GET_ALL_ROUTES, null, this);
}
Finally, I swap the cursor in the onLoadFinished() callback method as part of the LoaderManager.Callback methods.
EDIT: I just realized that if I wait for the LoaderManager to finish loading (1-2 seconds), before swiping the the Fragment which holds the Loader, the content is displayed.
I don't know if that new info changes anything. I am still very much stuck and definitely need help.
I finally solved my problem and here is how :
1 - Change
FragmentPagerAdapter
toFragmentStatePagerAdapter
. The reason for that is thatFragmentPagerAdapter
does not recreate your Fragments if needed. It keeps everything in memory. So if your Fragment is not fully operational when it is created, or if you want to refresh it later on, you are in trouble.2 - Remove the LoaderManager structure from the Fragments and let the parent Activity deal with querying the database. This way, I could have the
FragmentStatePagerAdapter
instantiate an empty fragment at first, and then the activity could tell the adapter to recreate the Fragment once the query has returned. And for this re-creation, I needed theFragmentStatePagerAdapter
.3 - Overide the getItemPosition() of my FragmentStatePagerAdapter so that all the Fragments get recreated when I call
notifyDataSetChanged()
on the PagerAdapter:Because my fragments are not too complex and the data to load is not big, I don't mind recreating all the fragments I have. Therefore using
POSITION_NONE
is ok performance wise.I hope this little findings can help other people. =)