多次调用 FragmentTransaction.commit 出错

1、参考资料

关于FragmentTransaction无法Commit两次的原因寻求

2、错误代码

val beginTransaction = requireActivity().supportFragmentManager.beginTransaction()
requireActivity().supportFragmentManager.fragments.forEach {
    if (it::class == FragmentSearchResultMusic::class ||
        it::class == FragmentSearchResultAlbum::class ||
        it::class == FragmentSearchResultSinger::class
    ) {
        beginTransaction.remove(it)
        beginTransaction.commitAllowingStateLoss() // 注意!!!
    }
}
  • 抛出的异常信息是:commit already called

3、源码分析

  • 源码版本:androidx.fragment:fragment-ktx:1.2.5
  • 先看 FragmentTransaction 对象,是通过 beginTransaction() 方法获取的,深入看其源码实现:
# FragmentManager
@NonNull
public FragmentTransaction beginTransaction() {
    return new BackStackRecord(this);
}
  • 该方法返回的是一个 BackStackRecord 实例对象,继承了 FragmentTransaction抽象类,commit方法的具体实现就在该类中
  • 找到 commit 方法
#BackStackRecord
@Override
public int commit() {
    return commitInternal(false);
}
  • 最终调用的是 commitInternal 方法
#BackStackRecord
int commitInternal(boolean allowStateLoss) {
    if (mCommitted) throw new IllegalStateException("commit already called"); // 注意!!!在此抛出异常
    if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
        Log.v(TAG, "Commit: " + this);
        LogWriter logw = new LogWriter(TAG);
        PrintWriter pw = new PrintWriter(logw);
        dump("  ", pw);
        pw.close();
    }
    mCommitted = true; // 修改变量值
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex();
    } else {
        mIndex = -1;
    }
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}
  • mCommitted 变量值,初始为 false,调用一次 commitInternal,置为 true,此时再调用 commitInternal,会抛出 commit already called 异常。故我们使用 FragmentTransaction 时,每次 beginTransaction 得到的对象只能进行一次 commit 操作。要进行第二次 commit 只能再次通过 beginTransaction 得到新的 FragmentTransaction 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值