案列
现在很多项目的首页功能都是用一个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异常销毁的时候才会调用 比如横竖屏切换出现异常 等等