最近在做提交任务功能,成功提交后点击弹窗返回原来的界面时,程序崩溃了,于是便看了下日志,报错
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();
}
这样就解决问题了,当然此方法我个人用着还行,若有不对的地方,望各位大佬指正。