【Android策略】Can not perform this action after onSaveInstanceState with DialogFragment

友盟错误详情:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
	at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1323)
	at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1341)
	at android.app.BackStackRecord.commitInternal(BackStackRecord.java:597)
	at android.app.BackStackRecord.commit(BackStackRecord.java:575)
	at android.app.DialogFragment.show(DialogFragment.java:230)
	at com.storm.durian.activity.MainActivity$MyHandler.handleMessage(MainActivity.java:670)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loop(Looper.java:136)
	at android.app.ActivityThread.main(ActivityThread.java:5282)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:810)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
	at dalvik.system.NativeStart.main(Native Method)

根据错误,我们找到了相应的代码:

就是在handleMessage中做了如下操作:

 CheckInfoItem checkInfo = (CheckInfoItem) msg.obj;
                    theLayout.checkInfo = checkInfo;
                    SignDialogFragment dialog = SignDialogFragment.newInstance(checkInfo);
                    dialog.show(theLayout.getFragmentManager(), "SignDialog");
问题就出在这:

1、因为我是在onResume方法中调取了签到接口,然后拿到签单信息,弹出签到窗口,因此可能导致该异常发生。

2、onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错

3、解决方法就是把commit()方法替换成 commitAllowingStateLoss()

api中是这么解释commitAllowingStateLoss()

Like commit() but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
4、但是我们调用的是DialogFragment的show方法,我们来看一下show方法的源码

public void show(FragmentManager manager, String tag) {
        mDismissed = false;
        mShownByMe = true;
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commit();
    }
我们发现它是通过commit进行提交的,所以就会带来java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState的风险

5、为了解决这个问题,我的处理方式是:

public void showCheckInDialog(CheckInfoItem checkInfo) {
        SignDialogFragment dialog = SignDialogFragment.newInstance(checkInfo);
        //这里直接调用show方法会报java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        //因为show方法中是通过commit进行的提交(通过查看源码)
        //这里为了修复这个问题,使用commitAllowingStateLoss()方法
        //注意:DialogFragment是继承自android.app.Fragment,这里要注意同v4包中的Fragment区分,别调用串了
        //DialogFragment有自己的好处,可能也会带来别的问题
        //dialog.show(getFragmentManager(), "SignDialog");
        android.app.FragmentManager fm = getFragmentManager();
        android.app.FragmentTransaction ft = fm.beginTransaction();
        ft.add(dialog, "SignDialog");
        ft.commitAllowingStateLoss();
    }
这里我们通过自己手动添加完成,解决这个问题。

6、有很多可能性会造成java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState,在stackoverflow中有很多这样的案例,如果我的方法解决不了你的问题,你可以参考一下它们的
7、我发现解友盟上的这些bug还是挺费力的,不管是自己挖的坑还是别人挖的坑可怜




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值