选择正确的 Fragment #commitXXX() 函数

2022-06-05  本文已影响0人  Drew_MyINTYRE

Fragment commit 有如下4个函数可以选择:

public abstract int commit();
public abstract int commitAllowingStateLoss();
public abstract void commitNow();
public abstract void commitNowAllowingStateLoss();

但有时我们可能会碰到一个异常,信息如下:

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

大意是在 activity 的 onSaveInstanceState 调用后再 commit 的 Transaction 导致的异常。为了不抛出异常有人建议使用 commitAllowingStateLoss 来代替 commit

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

public int commitAllowingStateLoss() {
    return commitInternal(true);
}
int commitInternal(boolean allowStateLoss) {
    if (mCommitted) {
        throw new IllegalStateException("commit already called");
    }
    ......
    mCommitted = true;
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}
public void enqueueAction(Runnable action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        // 如果是 false,就需要做状态检查
        checkStateLoss();
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList<Runnable>();
        }
        mPendingActions.add(action);
        if (mPendingActions.size() == 1) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
        }
    }
}
private void checkStateLoss() {
  if (mStateSaved) {
    throw new IllegalStateException("Can not perform this action after onSaveInstanceState");
  }

  if (mNoTransactionsBecause != null) {
    throw new IllegalStateException("Can not perform this action inside of " + mNoTransactionsBecause);
  }
}

如果 activity 的状态被保存了,这里再提交就会检查这个状态,符合这个条件就抛出一个异常来终止应用进程。也就是说在 activity 调用了 onSaveInstanceState() 之后,再 commit一个事务就会出现该异常。那如果不想抛出异常,也可以很简单调用 commitAllowingStateLoss() 方法来略过这个检查就可以了,但是这是危险的,如果 activity 随后需要从它保存的状态中恢复,这个 commit 是会丢失的。因此它仅仅适用在 ui 状态的改变对用户来说是可以接受的,允许丢失一部分状态。

总结:

官方更推荐使用 commitNow()和 commitNowAllowingStateLoss() 来代替先执行 commit()/commitAllowingStateLoss()

上一篇 下一篇

猜你喜欢

热点阅读