DialogFragment 使用时出现IllegalStateException: Can not perform this action after onSaveInstanceState

    今天收到一个问题,检索日志后,看到了如下的错误提示:

AndroidRuntime: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
AndroidRuntime: 	at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:4)
AndroidRuntime: 	at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1)
AndroidRuntime: 	at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:12)
AndroidRuntime: 	at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:1)
AndroidRuntime: 	at android.support.v4.app.DialogFragment.show(DialogFragment.java:5)

    而这个问题所在的原因是因为DialogFragment 在使用show()方法时出现了问题,即在显示fragment时执行如下的代码:


    异常的原因是commit()方法在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState方法是在该Activity即将被销毁前调用来保存Activity数据的,如果在保存完状态后再给它添加Fragment就会出错。
    解决办法就是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的,那么查看DialogFragment 源码并没有找到使用commitAllowingStateLoss()的show方法,那么应该怎么办呢?
    思索一下:是否想到可以重写父类的show方法呢? 使用commitAllowingStateLoss() 来替换commit() 方法,然而,发现该方法使用了私有变量,这就尴尬了,咋办,立马又想到可以使用反射的技术,来修改父类的私有变量,来保证重写show方法后,其他的状态合法正常:
代码如下:

    /**
     * 重写父类show()方法
     * 避免出现java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
     */
    @Override
    public void show(FragmentManager manager, String tag) {
        try {
            Class cls = this.getClass().getSuperclass();
            if (cls == null) return;

            Field mDismissed = cls.getDeclaredField("mDismissed");
            Field mShownByMe = cls.getDeclaredField("mShownByMe");
            mDismissed.setAccessible(true);
            mShownByMe.setAccessible(true);
            mDismissed.setBoolean(this, false);
            mShownByMe.setBoolean(this, true);
        } catch (Exception e) {
            Log.e("DialogFragment", "show", e.fillInStackTrace());
        }
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }

经过测试,目前未发现其他问题,欢迎大家指出不合理的地方

    补充一下,网上有人说,点home键后,onSaveInstanceState()方法在onPause()之前执行,而我测试的结果是,先执行onPause()方法,后执行onSaveInstanceState()方法。
————————————————
本文是转载的,以备自己查阅,原文链接:https://blog.csdn.net/baidu_28027209/article/details/79740209

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值