案列

现在很多项目的首页功能都是用一个Activity去加载多个Fragment去显示切换内容,列如微信的首页就是这样实现的,然后通过调研show和hide方法对Fragment进行显示隐藏操作,以此达到显切换识图。

但现在在笔者的实际项目中遇到了一个问题,当内存不足的时候,宿主Activity就会被销毁,但是Fragment还是被缓存下来了,关于Fragment的缓存可以看这位博主的文章 写的很清楚,这里不错解释了,当再次调用show 和hide的时候发现都失效了,所有的Fragment都重叠在了一起,就会出现显示问题

解决

只需要自己在savedInstanceState方法中判断缓存,在onCreate的时候根据savedInstanceState是否为空来判断, 如果不为空直接取缓存 为空就走oncreate流程

 

代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    ……
    if (savedInstanceState != null) {
        //不为空说明缓存视图中有fragment实例,通过tag取出来
        FragmentManager fragmentManager= getFragmentManager();
        homeFragment1= (HomeFragment1) fragmentManager.findFragmentByTag("HomeFragment1");
        homegment2 = (HomeFragment2) fragmentManager.findFragmentByTag("HomeFragment2");  
   }else{
        homegment1 = findOrCreateFragment("HomeFragment1", HomeFragment1.class);
        homegment2 = findOrCreateFragment("HomeFragment2", HomeFragment2.class);
    }
    ……//数据绑定
}

 @Nullable
 private <T extends Fragment> T findOrCreateFragment(String tag, Class<T> fragmentClass) {
     Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
     if (fragment == null) {
         try {
             fragment = fragmentClass.newInstance();
         } catch (InstantiationException | IllegalAccessException e) {
             e.printStackTrace();
             return null;
         }
     }
     return (T) fragment;
 }

 /**
  * 通过该方法切换Fragments
  **/
private void switchToFragment(int position) {
    mSelectPosition = position;
    Fragment showFragment = mFragmentList.get(position);    
    if (showFragment != mLastFragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (mLastFragment != null) {
            transaction.hide(mLastFragment);
        }

        if (!showFragment.isAdded()) {
        // 隐藏当前的fragment,显示选中的fragment
           transaction.add(R.id.main_container, showFragment,                   showFragment.getClass().getName()).commitAllowingStateLoss();
        } else {
        // 隐藏当前的fragment,显示选中的fragment
            transaction.show(showFragment).commitAllowingStateLoss();
        }
        mLastFragment = showFragment;
     }

扩展

savedInstanceState

onCreate方法的完整定义如下:

public void onCreate(Bundle savedInstanceState){
       super.onCreate(savedInstanceState);
}

   从上面的代码可以看出,onCreate方法的参数是一个Bundle类型的参数。Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的。从字面上看savedInstanceState,是保存实例状态的。实际上,savedInstanceState也就是保存Activity的状态的。那么,savedInstanceState中的状态数据是从何处而来的呢?下面我们介绍Activity的另一个方法saveInstanceState。

  onsaveInstanceState方法是用来保存Activity的状态的。当一个Activity在生命周期结束前,会调用该方法保存状态。这个方法有一个参数名称与onCreate方法参数名称相同。如下所示:

public void onSaveInstanceState(Bundle savedInstanceState){
       super.onSaveInstanceState(savedInsanceState);
}

    在实际应用中,当一个Activity结束前,如果需要保存状态,就在onsaveInstanceState中,将状态数据以key-value的形式放入到savedInstanceState中。这样,当一个Activity被创建时,就能从onCreate的参数savedInsanceState中获得状态数据。

onSaveInstanceState()这个方法只有在Activity异常销毁的时候才会调用 比如横竖屏切换出现异常 等等