Reputation: 359
I have this situation,
Activity -> RestaurantsFragment -> [viewPager / FragmentPageAdapter] Two Fragments
I want to retain all the fragments after the screen rotation but what happens is that
Here is my code...
Activity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
....
if (savedInstanceState== null) {
fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMNET_RESTAURANTS);
if(fragment==null) {
fragment = new RestaurantsFragment();
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frame_container, fragment, (TAG_FRAGMNET_RESTAURANTS);
}
....
}
RestaurantsFragment.java
private TabsRestaurantsAdapter tabsRestaurantsAdapter;
private ViewPager viewPager;
private int position;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Luigi-RFragment-" + id, "onCreate");
setRetainInstance(true);
Log.d("Luigi-RFragment-" + id, "savedInstanceState==null");
tabsRestaurantsAdapter = new TabsRestaurantsAdapter(getChildFragmentManager());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("Luigi-RFragment-" + id, "onCreateView");
View rootView = inflater.inflate(R.layout.ristoranti_fragment, container, false);
viewPager = (ViewPager) rootView.findViewById(R.id.pager);
viewPager.setAdapter(tabsRestaurantsAdapter);
position = 0;
if (savedInstanceState != null) {
position = savedInstanceState.getInt("position");
}
viewPager.setCurrentItem(position);
setHasOptionsMenu(true);
return rootView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("position", viewPager.getCurrentItem());
}
TabsRestaurantsAdapter.java
public class TabsRestaurantsAdapter extends FragmentPagerAdapter {
private String titles[] = new String[]{"I TUOI PREFERITI", "TUTTI"};
private MenusFavTabFragment menusFavTabFragment;
private RestaurantsAllTabFragment restaurantsAllTabFragment;
public TabsRestaurantsAdapter(FragmentManager fm) {
super(fm);
menusFavTabFragment = new MenusFavTabFragment();
restaurantsAllTabFragment = new RestaurantsAllTabFragment();
}
@Override
public Fragment getItem(int index) {
Log.d("Luigi-adapter", "getItem" + index);
switch (index) {
case 0:
// Favourite Fragment
return menusFavTabFragment;
case 1:
// All Restaurant
return restaurantsAllTabFragment;
}
return null;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment f = (Fragment) super.instantiateItem(container, position);
return f;
}
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public int getCount() {
// get item count - equal to number of tabs
return titles.length;
}
}
Consider that when the RestaurantsFragment is reattached, the adapter (old) is setted again in the viewPager and the method of the adapter instantiateItem is invoked
The two fragments nested have nothing special
( I have also tried to recreate a new adapter each time (managing thre reuse of the old fragments) and it works but only for one rotation...but why should i recreate the adapter ? )
Why they do not appear?
Thanks.
Upvotes: 0
Views: 681
Reputation: 779
This appears to be fixed in the support library version 24.
The call to onAttach() shown in the workaround was causing a NPE in the containing activity's super.onCreate() method during rotation. On a whim, I removed the onAttach() code since this NPE only occurred in the Activity/Fragment where I had implemented the solution. After removing the call to onAttach(), the NPE went away and it appears as though my code is working as expected.
See: https://code.google.com/p/android/issues/detail?id=197271
Upvotes: 0
Reputation: 359
Thanks Thanks Thanks @hegazy
I discovered and applyed this workaround and now it works:
retain the childFragmentManager and reassign it to the Field object
the new RestaurantsFragment.java
//the global childFragmentManager
private FragmentManager mRetainedChildFragmentManager;
public void onAttach(Activity activity) {
super.onAttach(activity);
//To fix the bug with library v4
if (mRetainedChildFragmentManager != null) {
//restore the last retained child fragment manager to the new
//created fragment
try {
Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
childFMField.setAccessible(true);
childFMField.set(this, mRetainedChildFragmentManager);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
mRetainedChildFragmentManager = getChildFragmentManager();
}
}
I hope this can help you !
Upvotes: 1
Reputation: 12605
This a bug in the support library v4.
For more info Nested fragments not being retained in support library.
Personally, I do the nasty thing of setting the configuration changes on my manifest to orientation
and screenSize
. I didn't give myself a time to think of a better way ;)
Upvotes: 1