如题,Android开发中很多人使用这种方式来布局,其具体实现不再赘述。
问题:
在一次偶然的情况下,应用被放在后台N久,然后又打开了应用,乍一看没啥问题,然后切换了一下tab,发现之前的fragment居然在当前fragment后面不消失。当然你也可以在开发者选项中,勾选不保留活动这一项可以迅速发现这一情况。
原因分析:在异常生命周期下(如内存不足等),activity会被回收,此时会调用onSaveInstanceState()保存当前的图层,之后如果重启该activity,则会恢复之前的图层(包括显示的fragment)。此时我们再切换时,会新建对应的fragment,而恢复的那个由于没有隐藏,依旧显示,造成重影。
解决方案:
1.去掉onSaveInstanceSate()方法的默认实现,这样就不会保存图层,在需要时直接重建就行。但是官方文档推荐是:总是默认该实现。因此不推荐此方法,这也是网上唯一能找到的解决方案。
2.在新建fragment时,用tag或者id标记该fragment。而在新建之前要在FragmentManager中通过find方法查找是否已经存在指定的fragment,存在了直接获取该实例,不存在则再新建,这样就不会出现重复的fragment。
代码示例:
@Override public void onCheckedChanged(RadioGroup group, int checkedId) { FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); //单选按钮切换时,先隐藏所有fragment hideAllFragment(fragmentTransaction); switch (checkedId) { case R.id.rb_a: if (mFragmentA == null) { mFragmentA = new AFragment(); fragmentTransaction.add(R.id.fl_main, mFragmentA, TAG_FRAGMENT_A); } else { fragmentTransaction.show(mFragmentA); } break; case R.id.rb_b: if (mFragmentB == null) { mFragmentB = new BFragment(); fragmentTransaction.add(R.id.fl_main, mFragmentB, TAG_FRAGMENT_B); } else { fragmentTransaction.show(mFragmentB); } break; case R.id.rb_c: if (mFragmentC == null) { mFragmentC = new CFragment(); fragmentTransaction.add(R.id.fl_main, mFragmentC, TAG_FRAGMENT_C); } else { fragmentTransaction.show(mFragmentC); } break; } fragmentTransaction.commitAllowingStateLoss(); } /** * 隐藏所有的fragment */ private void hideAllFragment(FragmentTransaction fragmentTransaction) { // 此处首先获取之前已经存在的fragment,原因:在非正常生命周期下,onSaveInstance方法会保存 // 当前fragment的图层,重新创建后如果产生切换事件,那么由于这些fragment还没初始化,则会 // 重新创建,会导致fragment的重影效果。 getAllFragmentByTag(); if (mFragmentA != null) { fragmentTransaction.hide(mFragmentA ); } if (mFragmentB != null) { fragmentTransaction.hide(mFragmentB); } if (mFragmentC != null) { fragmentTransaction.hide(mFragmentC); } } /** * 通过tag获取之前的fragment */ private void getAllFragmentByTag() { if (mFragmentA == null) {
} if (mFragmentB == null) { mFragmentB = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_B); } if (mFragmentC == null) { mFragmentC = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_C); }}mFragmentA = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_A);