最近在做提交任务功能,成功提交后点击弹窗返回原来的界面时,程序崩溃了,于是便看了下日志,报错
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
字面意思:在onSaveInstanceState之后无法执行此操作
于是慢慢定位到错误的地方,最外层是表示在我的回调函数里dialog的展示有问题,看不出个啥,于是往最里层看,就到了这里
看到这里,大概也知道啥原因了,上次就出现过,没总结,这次可不能放过了。关于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(); }
这样就解决问题了,当然此方法我个人用着还行,若有不对的地方,望各位大佬指正。