Tab+Fragment异常生命周期下产生的fragment重影问题

如题,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) {
        mFragmentA = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_A);
} if (mFragmentB == null) { mFragmentB = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_B); } if (mFragmentC == null) { mFragmentC = mFragmentManager.findFragmentByTag(TAG_FRAGMENT_C); }}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值