java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState(已解决)

最近在做提交任务功能,成功提交后点击弹窗返回原来的界面时,程序崩溃了,于是便看了下日志,报错

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 

字面意思:在onSaveInstanceState之后无法执行此操作  

于是慢慢定位到错误的地方,最外层是表示在我的回调函数里dialog的展示有问题,看不出个啥,于是往最里层看,就到了这里

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState(已解决)_第1张图片

看到这里,大概也知道啥原因了,上次就出现过,没总结,这次可不能放过了。关于DialogFragment其实也是一个fragment,只是其内部绑定了dialog,用于各类弹窗,挺好用的,给个学习链接:https://www.jianshu.com/p/d1852b04a0aa。

这里是指在执行onSaveInstanceState之后再调用FragmentTransaction的commit方法导致异常的发生。

原因:commit()方法是在Activity的onSaveInstanceState()之后调用的,使用commit提交的时候会调用到onSaveInstanceState(),而调用onSaveInstanceState()的同时系统就会回收Activity,从而造成整个App的闪退。

解决办法:官方给的解决方法是使用commitAllowingStateLoss方法。

代码实际操作:

利用try catch方法

源代码:我是写了个BaseDialogFragment继承DialogFragment,这样操作性更强一些

   public void show(final String tag) {
        ThreadUtils.runOnUiThread(new Runnable() {
            @SuppressLint("CommitTransaction")
            @Override
            public void run() {
                if (ActivityUtils.isActivityAlive(mActivity)) {
                    FragmentManager fm = mActivity.getSupportFragmentManager();
                    Fragment prev = fm.findFragmentByTag(tag);
                    if (prev != null) {
                        fm.beginTransaction().remove(prev);
                    }
                    BaseDialogFragment.super.show(fm, tag);
                }
            }
        });
    }

更改后:

 public void show(final String tag) {
        ThreadUtils.runOnUiThread(new Runnable() {
            @SuppressLint("CommitTransaction")
            @Override
            public void run() {
                if (ActivityUtils.isActivityAlive(mActivity)) {
                    FragmentManager fm = mActivity.getSupportFragmentManager();
                    Fragment prev = fm.findFragmentByTag(tag);
                    if (prev != null) {
                        fm.beginTransaction().remove(prev);
                    }
                    /*我这儿用的是try-catch
                     *当然也可以直接一刀切,不用commit方法,直接方法一
                     *FragmentTransaction ft = fm.beginTransaction();
                     *ft.add(BaseDialogFragment.this, tag);
                     *ft.commitAllowingStateLoss();
                     */
                    try {
                        BaseDialogFragment.super.show(fm, tag);

                    }catch (IllegalStateException ignore){
                        showAllowingStateLoss(fm,tag);//在这儿调用showAllowingStateLoss
                    }
                }
            }
        });
    }

    public void showAllowingStateLoss(FragmentManager manager, String tag){
        try {
            Field dismissed = DialogFragment.class.getDeclaredField("mDismissed");
            dismissed.setAccessible(true);
            dismissed.set(this, false);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        try {
            Field shown = DialogFragment.class.getDeclaredField("mShownByMe");
            shown.setAccessible(true);
            shown.set(this, true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    } 

这样就解决问题了,当然此方法我个人用着还行,若有不对的地方,望各位大佬指正。

 

 

你可能感兴趣的:(Android开发Bug日志,Android开发,android)