fragment重影解决
造成fragment重影的原因
造成fragment重影的原因是因为我们代码里用add fragment 然后调用hide和show来替换replace方式(因为这样做不用每次切换fragment都重新加载界面和数据)。但是正因为这样当我们activity异常关闭重启时你原先的所有fragment也都会跟着activity重新绘制出来,然而这个时候所有的hide和show失灵了,因为我们默认是没有找到系统帮我们恢复的fragment,而是自己又重新new了一个fragment出来,所以解决这个问题的核心就是找到系统帮我恢复的fragment并操作相应方法
解决方法
在写解放方法前,先贴出我们常用操作fragment的通用方法
/**
* 跳转到fragment
*
* @param fragmentFrom Fragment
* @param fragmentTo Fragment
* @param bundle Bundle
*/
private void commitFragment(Fragment fragmentFrom, Fragment fragmentTo, Bundle bundle) {
mCurrentFragment = (BaseFragment) fragmentTo;
if (bundle != null) {
fragmentTo.setArguments(bundle);
}
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
if (fragmentFrom == null) {
ft.remove(fragmentTo).commit();
ft=fm.beginTransaction();
ft.add(R.id.main_fragment_container, fragmentTo, fragmentTo.getClass().getName());
ft.addToBackStack(null);
ft.commit();
return;
}
if (fragmentTo.isAdded()) {
ft.hide(fragmentFrom).show(fragmentTo).commit();
fm.executePendingTransactions();
} else {
ft.remove(fragmentTo).commit();
ft=fm.beginTransaction();
ft.hide(fragmentFrom).add(R.id.main_fragment_container, fragmentTo, fragmentTo.getClass().getName());
ft.addToBackStack(null);
ft.commit();
}
}
方法1:通过 FragmentManager().findFragmentByTag解决
这个方法比较通用,不管在那种场景下都可以通过这个解决,我们add fragment的时候添加一个tag,即上边通用代码中的fragmentTo.getClass().getName(),当系统异常重新启动activity和fragment的时候 我们通过判断
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
中的savedInstanceState!=null来找到系统帮我恢复的fragment
并赋值给你的变量中制定的fragment如:
appMenagementFragmen=(AppManagementFragment)getFragmentManager().findFragmentByTag(AppManagementFragment.class.getName());
- 方法2:适合于fragment没有在嵌套fragment(常用MainActivity里有几个fragment)
这种方法可以重写activity的onAttachFragment方法,在里边找到系统帮我们恢复的fragment并赋值给我们的变量,并隐藏他们,如:
@Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
if(mMarketFragment==null && fragment instanceof MarketFragment2){
mMarketFragment=(MarketFragment2)fragment;
getSupportFragmentManager().beginTransaction().hide(mMarketFragment).commit();
}else if(mAppFragment==null && fragment instanceof MyappFragment){
mAppFragment=(MyappFragment)fragment;
getSupportFragmentManager().beginTransaction().hide(mAppFragment).commit();
}else if(mContactFragment==null && fragment instanceof ContactFragment){
mContactFragment=(ContactFragment)fragment;
getSupportFragmentManager().beginTransaction().hide(mContactFragment).commit();
}else if(mNoticeFragment==null && fragment instanceof MsgFragment){
mNoticeFragment=(MsgFragment)fragment;
getSupportFragmentManager().beginTransaction().hide(mNoticeFragment).commit();
}
}
需要注意的地方
1、上述两种方法涉及到数据恢复和一些自己界面操作的要自己通过重写onSaveInstanceState和onRestoreInstanceState来实现,如要恢复activity重新进来主页时恢复上次选择的radiobutton,其他数据也一样:
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
if(mGroup!=null)
outState.putInt("checkID",mGroup.getCheckedRadioButtonId());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
checkID=savedInstanceState.getInt("checkID",-1);
}
2、 有些同学使用FragmentPagerAdapter,发现程序切到后台重新启动的时候有些页面数据是空白,这是因为new Adapter的时候传入的参数不对。其中MarketPageApapter继承与FragmentPagerAdapter
/**
*正确的写法
*/
mPager.setAdapter(new MarketPageAdapter(this.getChildFragmentManager(), fragments));
/**
*错误的写法
*/
mPager.setAdapter(new MarketPageAdapter(getFragmentManager(), fragments));