• FragmentManager is already executing transactions异常


    错误日志

     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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    触发场景

    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;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    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;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    上述代码中的变量mExecutingActions会在第一次执行时置为true,由于代码是同步的且所有的相关操作都在主线程,不存在多线程,所以在上次操作尚未结束时(mExecutingActions尚未置为false)再次调用此方法,就会抛出异常。

    解决办法

    通过异步的方式可以解决掉此问题。

    推荐方法:使用为commitAllowingStateLoss()替换执行,commitAllowingStateLoss()方法为异步执行,可以规避掉此问题的出现。

  • 相关阅读:
    mac版微信小程序反编译学习
    实时音视频方案汇总
    JavaWeb-高级分页查询
    无线图传模块选型参考
    北大青鸟培训后端培训第二天
    Nacos的集群、负载均衡、环境隔离
    JS 的 apply 方法
    pgAdmin Crypt key missing
    【C++11】右值引用、移动构造、移动赋值、完美转发 的原理介绍
    Temporal线上部署
  • 原文地址:https://blog.csdn.net/cat_is_so_cute/article/details/132765815