美文网首页
Can not perform this action afte

Can not perform this action afte

作者: 陈萍儿Candy | 来源:发表于2020-11-30 11:47 被阅读0次

1.onSaveInstanceState()方法的调用时机
在 Activity 被销毁之前被调用来保存每个实例的状态,这样就可以保证该状态能够从 onCreate(Bundle) 或者onRestoreInstanceState(Bundle)恢复过来。

本方法在 Activity 可能被销毁前调用,这样当该 Activity 在将来某个时刻重新回来时可以恢复其之前的状态。例如,如果 Activity B 启用后位于 Activity A 的前端,在某个时刻 Activity A 因为系统回收资源的原因要被销毁,Activity A 有机会通过 onSaveInstanceState() 来保存其用户界面状态,使得将来用户返回到 Activity A 的时候能够通过 onCreate(Bundle) 或者onRestoreInstanceState(Bundle) 来恢复其界面状态。

不要将这个方法和 Activity 生命周期中的回调如 onPause() 或 onStop() 搞混淆了,onPause() 在 Activtiy 被放置到后台或者自行销毁时总会被调用,onStop() 在 Activity 被销毁时被调用。一个会调用 onPause() 和 onStop() 但不会触发 onSaveInstanceState() 的例子是当用户从 Activity B 返回到 Activity A 时:没有必要调用 B 的 onSaveInstanceState(Bundle)方法,因为此时的 B 实例永远不会被恢复,因此系统会避免调用它。一个调用 onPause() 但不调用 onSaveInstanceState(Bundle) 方法的例子是当 Activity B 启动后处在 Activity A 的前端:如果在B的整个生命周期里 A 的用户界面状态都没有被破坏的话,系统是不会调用 Activity A 的onSaveInstanceState(Bundle)方法。

View中也有onSaveInstanceState()来保存view的状态
activity的onSaveInstanceState方法中会调用FragmentManager#saveAllState方法,来进行Fragment的状态保存,同时设置mStateSaved为true,用来标识状态已被保存过.

有两种情况会出现Can not perform this action after onSaveInstanceState异常:
1.FragmentTransaction的commit()时出现:
2.Activity/FragmentActivity的onBackPressed时出现:
这两种情况都是在存储状态后调用了commit或者onBackPressed等方法,这些方法会调用checkStateLoss();抛出异常

 private void checkStateLoss() {
        if (isStateSaved()) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
    }

首先看下commit和commitAllowingStateLoss方法区别:

@Override
    public int commit() {
        return commitInternal(false);
    }

    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

commitInternal方法会调用到enqueueAction方法,如果allowStateLoss为false会检查状态,抛出异常;

public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<>();
            }
            mPendingActions.add(action);
            scheduleCommit();
        }
    }

所以,事务要尽早提交,或者使用commitAllowingStateLoss
除此之外,在onBackPressed方法中也会触发checkStateLoss()方法,
比如:Activity/FragmentActivity的onBackPressed时出现

@Override
    public void onBackPressed() {
        if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
            super.onBackPressed();
        }
    }


会调用FragmentManagerImpl的popBackStackImmediate()方法,如下:

@Override
    public boolean popBackStackImmediate() {
        checkStateLoss();
        return popBackStackImmediate(null, -1, 0);
    }

其实FragmentManagerImpl的popBackStack相关方法基本都有机会触发checkStateLoss();

......前面还有其他popBackStack方法
@Override
    public void popBackStack() {
        enqueueAction(new PopBackStackState(null, -1, 0), false);
    }

    @Override
    public boolean popBackStackImmediate() {
        checkStateLoss();
        return popBackStackImmediate(null, -1, 0);
    }

    @Override
    public void popBackStack(@Nullable final String name, final int flags) {
        enqueueAction(new PopBackStackState(name, -1, flags), false);
    }

    @Override
    public boolean popBackStackImmediate(@Nullable String name, int flags) {
        checkStateLoss();
        return popBackStackImmediate(name, -1, flags);
    }

enqueueAction方法当boolean allowStateLoss参数传入为false时,就会走checkStateLoss();方法检测存储状态,就有可能抛出异常;

参考:https://blog.csdn.net/liuwei187/article/details/90264751
https://www.cnblogs.com/xhj-records/archive/2013/02/28/2936373.html

相关文章

网友评论

      本文标题:Can not perform this action afte

      本文链接:https://www.haomeiwen.com/subject/pjdrwktx.html