原因分析
Activity添加Fragment后,Activity会保存所有被添加的Fragment的状态;由于系统内存等问题Activity被回收后,Activity会自己重新创建原来保存的这些Fragment并attach;但我们如果使用引用方式保存并使用ViewPager里的Fragment,会造成异常;
问题解决
方案1
Activity不要调用父类保存Fragment状态的方法;
@Override
protected void onSaveInstanceState(Bundle outState) {
// super.onSaveInstanceState(outState);
}
方案2
在Fragment的onCreate方法开始调用下面方法,清除当前Fragment所属的所有子Fragment;
private void clearFragments(){
FragmentManager fm = getChildFragmentManager();
if(fm != null && fm.getFragments() != null && fm.getFragments().size() > 0){
FragmentTransaction ft = fm.beginTransaction();
for(Fragment fragment : fm.getFragments()){
ft.remove(fragment);
}
ft.commit();
}
}
方案3
覆写Activity的onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState != null){
savedInstanceState.remove("android:support:fragments");
}
super.onCreate(savedInstanceState);
...
}
方案4
获取ViewPager里的Fragment时,不要通过引用方式获取,改为如下方式获取:
/**
* ViewPager根据position找指定位置的Fragment
* @param fragmentManager
* @param viewPagerId
* @param fragmentPagerAdapter
* @param position
* @return
*/
public static Fragment getFragment(FragmentManager fragmentManager, int viewPagerId, FragmentPagerAdapter fragmentPagerAdapter, int position){
if(fragmentManager != null){
String tag;
if(fragmentPagerAdapter != null){
tag = "android:switcher:" + viewPagerId + ":" + fragmentPagerAdapter.getItemId(position);
} else {
tag = "android:switcher:" + viewPagerId + ":" + position;
}
return fragmentManager.findFragmentByTag(tag);
} else {
return null;
}
}
结论
上面四种方式,均可解决Activity自己重建Fragment造成的一些问题;但方案1、方案2、方案3可维护性及可扩展性不好,推荐使用方案4;
问题思考
1. 方案2中,Activity销毁被重建时,子Fragment会被自动重建,但在onCreate用代码清除后,后面会由我们的业务代码再重新创建;
2. 方案1、方案2、方案3其实都是在想办法清除掉原有的Fragment及其状态,方案4只是修改了获取Fragment的方式,较好地保留了原有Fragment状态逻辑;