多次调用 FragmentTransaction.commit 出错
多次调用 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对象。
更多推荐

所有评论(0)