今天遇到一个Fragment内显示ViewPager,ViewPager的view也是Fragment的相关问题,最开始使用的是FragmentStatePagerAdapter。出现第一次进入Fragment时,viewpager正常显示数据,当第二次进来时,就无法显示数据,经过打印信息测试,发现第二次进来时并没有走Viewpager显示的Fragment的oncreateview和onactivitycreated方法。开始以为时viewpager的预加载特性导致的。后来在网上各种查,最开始的解决方案是按照这篇博客的方法点击打开链接,针对FragmentPagerAdapter的解决办法如下代码:
@Override
public Fragment getItem(int position) {
MyFragment f = new MyFragment();
return f;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
MyFragment f = (MyFragment) super.instantiateItem(container, position);
String title = mList.get(position);
f.setTitle(title);
return f;
}
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
发现然并卵,第二次进来依然没有数据,关键的是没有view,因为我在instantiateItem方法内让一个隐藏的图片显示,都没有成功。之后又是各种查资料。终于成功了。因为我的这个问题可能比单纯的不显示数据还要复杂一些。解决方法是:
(要确保是Fragment里面套用Fragment)
①显示ViewPager的Fragment获取FragmentManager时不能用getActivity().getSupportFragmentManager()了,要改用getChildFragmentManager()。
仅仅是这样,会出现异常:java.lang.IllegalStateException: No activity
出现场景:第一次启动程序可以正常运行,随便切换pager也不会有问题,第二次必崩!
是什么引起的bug
If you look at the implementation of Fragment, you'll see that when moving to the detached state, it'll reset its internal state. However, it doesn't reset mChildFragmentManager (this is a bug in the current version of the support library). This causes it to not reattach the child fragment manager when the Fragment is reattached, causing the exception you saw.
②修复Bug,
bug原理:This seems to be a bug in the newly added support for nested fragments. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity. A short-term workaround that fixed it for me is to add the following to onDetach() of every Fragment which you call getChildFragmentManager() on
在这个Fragment里重写onDetach方法:(这段代码直接复制,不需要修改,Field的包名是java.lang.reflect.Field)
@Override
public void onDetach() {
// TODO Auto-generated method stub
super.onDetach();
try {
Field childFragmentManager = Fragment.class
.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
如果用的是FragmentStatePagerAdapter这种写法会出现 java.lang.IllegalStateException:Fragement no longer exists for key f0: index 0异常,所以要确保使用的是FragmentPagerAdapter。两种方法都是有用的,看看是要解决哪种问题。