Fragment:java.lang.IllegalStateException Can not perform this action after onSaveInstanceState

异常

java.lang.IllegalStateException
  Can not perform this action after onSaveInstanceState
  android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053)
  android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079)
  android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678)
  android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632)
  com.xxx.ui.fragment.xxx.a(XXXFragment.java:171)

处理方案

 transaction.show(toShowFragment).commit();

换成

 transaction.show(toShowFragment).commitAllowingStateLoss();

原因

就是因为 不能在onSaveInstanceState这个方法之后调用commit方法

为什么commitAllowingStateLoss可以而commit不可以

对比两个方法源码

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

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

可以看到就是一个简单的布尔值入参不同,追踪下这个布尔值的最终使用的地方(allowStateLoss)

    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();
        }
    }

可以看到就两处使用到了这个变量值

  • 第一处:(异常就是从这个地方抛出的)
    private void checkStateLoss() {
        if (isStateSaved()) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mNoTransactionsBecause != null) {
            throw new IllegalStateException(
                    "Can not perform this action inside of " + mNoTransactionsBecause);
        }
    }
  • 第二处:
            if (mDestroyed || mHost == null) {
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }

从上面这些代码看来,两个方法的区别仅仅是是否会抛出异常,并没有更多额外的处理。

那么问题来了,能不能全部都直接使用commitAllowingStateLoss 而不使用commit,从上面的源码层面来看并没有什么实际影响,使用两个方法主要区别是:
commitAllowingStateLoss :不校验是否在onSaveInstanceState之后,不校验是否mDestroyed,也不校验mHost(宿主关联工具类)
commit:和上面相反,会校验上面那些内容,也就是发现已经onSaveInstanceState或者mDestroyedmHost==null 的时候,会抛出异常提示。

所以全部都用commitAllowingStateLoss 的时候在大多数场景是没有什么问题的(并不会影响到正常场景的状态信息保存),只是在可能丢失状态的时候不会给到异常提示。

你可能感兴趣的:(Fragment:java.lang.IllegalStateException Can not perform this action after onSaveInstanceState)