美文网首页
选择正确的 Fragment #commitXXX() 函数

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

作者: Drew_MyINTYRE | 来源:发表于2022-06-05 21:30 被阅读0次

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

  • commit()
public abstract int commit();
  • commitAllowingStateLoss()
public abstract int commitAllowingStateLoss();
  • commitNow()
public abstract void commitNow();
  • commitNowAllowingStateLoss()
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 状态的改变对用户来说是可以接受的,允许丢失一部分状态。

总结:

  • 在 Activity 的生命周期方法中提交事务要小心,越早越好,比如 onCreate。尽量避免在 onActivityResult()方法中提交。

  • 避免在异步的回调方法中执行 commit,因为他们感知不到当前 Activity 生命周期的状态。

  • 使用 commitAllowingStateLoss() 代替 commit()。相比于异常 crash,UI 状态的改变对用户来说是可以接受的。

  • 如果你需要在 Activity 执行完 onSaveInstanceState() 之后还要进行提交,而且不关心恢复时是否会丢失此次提交,那么可以使用commitAllowingStateLoss()commitNowAllowingStateLoss()

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

相关文章

网友评论

      本文标题:选择正确的 Fragment #commitXXX() 函数

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