java.lang.IllegalStateException: FragmentManager is already executing transactions
at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1931)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1967)
at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311)
at com.example.genework1.base.BaseActivity.addFragmentNow(BaseActivity.java:24)
at com.example.genework1.activity.TestCommitActivity.openPage(TestCommitActivity.java:22)
at com.example.genework1.fragment.TestFragment1.onViewCreated(TestFragment1.java:26)
Activity继承了接口IAction,其方法中打开Fragment2
public class TestCommitActivity extends BaseActivity implements IAction {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_commit);
addFragmentNow(R.id.content, new TestFragment1());
}
@Override
public void openPage() {
addFragmentNow(R.id.content, new TestFragment2());
}
protected final Fragment addFragmentNow(int id, Fragment fragment) {
if (fragment == null)
return null;
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.INITIALIZED)) {
getSupportFragmentManager().beginTransaction().add(id, fragment).commitNowAllowingStateLoss();
return fragment;
}
return null;
}
}
Activity中添加了一个Fragment1,在Fragment1的onViewCreated方法中回调Activity中onPage
方法打开界面Fragment2,发生错误。
出现此问题的原因是FragmentManager的一次操作未结束时又触发了新的操作,而调用的方法又是commitNowAllowingStateLoss()
,触发了如下方法:
private void ensureExecReady(boolean allowStateLoss) {
if (mExecutingActions) {
throw new IllegalStateException("FragmentManager is already executing transactions");
}
if (mHost == null) {
if (mDestroyed) {
throw new IllegalStateException("FragmentManager has been destroyed");
} else {
throw new IllegalStateException("FragmentManager has not been attached to a host.");
}
}
if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of fragment host");
}
if (!allowStateLoss) {
checkStateLoss();
}
if (mTmpRecords == null) {
mTmpRecords = new ArrayList<>();
mTmpIsPop = new ArrayList<>();
}
mExecutingActions = true;
try {
executePostponedTransaction(null, null);
} finally {
mExecutingActions = false;
}
}
上述代码中的变量mExecutingActions
会在第一次执行时置为true,由于代码是同步的且所有的相关操作都在主线程,不存在多线程,所以在上次操作尚未结束时(mExecutingActions尚未置为false)再次调用此方法,就会抛出异常。
通过异步的方式可以解决掉此问题。
推荐方法:使用为commitAllowingStateLoss()
替换执行,commitAllowingStateLoss()
方法为异步执行,可以规避掉此问题的出现。