DialogFragment使用中show()方法遇到的IllegalStateException
来源:互联网 发布:伪娘 知乎 编辑:程序博客网 时间:2024/06/06 00:03
最近在首页做了一个弹窗,用dialogFragment 实现的,线上报了一个crash:
ava.lang.IllegalStateException: Can not perform this action after onSaveInstanceStateat android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)特此记录一下。
此问题的原因是:mainActivity 调用了onSaveInstanceState()以后有触发了dialog的显示,dialog.show()方法里边用的是commit()而不是commitAllowingStateLoss()
追踪一下代码:
DialogFragment中:
public void show(FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); }
从调用下手:
dialog.show(getActivity().getSupportFragmentManager(), "");
可以追踪下去,第一个参数manager是:
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentTransaction ft = manager.beginTransaction();
@Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); }
BackStackRecord中:
public int commit() { return commitInternal(false); }public int commitAllowingStateLoss() { return commitInternal(true); }
可以看到这俩函数的区别就是commitInternal()方法中参数一个为true,一个为false,看一下这个函数:
int commitInternal(boolean allowStateLoss) { if (mCommitted) throw new IllegalStateException("commit already called"); if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter logw = new LogWriter(TAG); PrintWriter pw = new PrintWriter(logw); dump(" ", null, pw, null); } mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); } else { mIndex = -1; } mManager.enqueueAction(this, allowStateLoss); return mIndex; }再追踪到enqueueAction(this,allowStateLoss):
public void enqueueAction(Runnable action, boolean allowStateLoss) { if (!allowStateLoss) { checkStateLoss(); } synchronized (this) { if (mDestroyed || mHost == null) { throw new IllegalStateException("Activity has been destroyed"); } if (mPendingActions == null) { mPendingActions = new ArrayList<Runnable>(); } mPendingActions.add(action); if (mPendingActions.size() == 1) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } }可以看到函数第一行根据allowStateLoss做了一个判断,看一下checkStateLoss():
private void checkStateLoss() { if (mStateSaved) { throw new IllegalStateException( "Can not perform this action after onSaveInstanceState"); } if (mNoTransactionsBecause != null) { throw new IllegalStateException( "Can not perform this action inside of " + mNoTransactionsBecause); } }
怎么样,终于把这个异常信息给抓出来了吧,特么的,
知道了bug原因那我们来说一下解决吧,有人说用反射的方法拿到commitAllowingStateLoss()方法,调用他,但是这也太麻烦了,所简单点的办法就是:
重写show方法catch住异常即可,做好容错处理:
/** * 为了解决:mainActivity调用onSaveInstanceState以后又调用了show方法, * 出现的Can not perform this action after onSaveInstanceState * 这个异常(不应该用commit ,而是用commitAllowingStateLoss) * 得罪了,不会反射 ,先把你catch住吧.乖 * @param manager * @param tag */ @Override public void show(FragmentManager manager, String tag) { try { super.show(manager, tag); } catch (IllegalStateException ignore) { // 容错处理,不做操作 } }
另外别忘记dissmiss也要做处理:
/** * 注意,不要用super.dismiss(),bug 同上show() * super.onDismiss就没问题 */ public void dismissDialog() { if ( getActivity() != null && !getActivity().isFinishing()) { super.dismissAllowingStateLoss(); } }而这个方法是没问题的:
@Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); }因为他调用的就是:
public void onDismiss(DialogInterface dialog) { if (!mViewDestroyed) { // Note: we need to use allowStateLoss, because the dialog // dispatches this asynchronously so we can receive the call // after the activity is paused. Worst case, when the user comes // back to the activity they see the dialog again. dismissInternal(true); } }好了,特此纪念一下,再犯此错误,
0 0
- DialogFragment使用中show()方法遇到的IllegalStateException
- 使用DialogFragment遇到的一些问题
- DialogFragment使用时遇到的一些问题
- 使用DialogFragment实现登录遇到的坑
- Android中DialogFragment的使用
- 项目练习中遇到的ILLEGALSTATEException
- CollapsingToolbarLayout使用时遇到的IllegalStateException异常
- android中DialogFragment的一些使用笔记
- C#中方法Show.和ShowDialog的使用区别
- C#中方法Show和ShowDialog的使用区别
- C#中方法Show和ShowDialog的使用区别
- Fragment中使用ViewPager,ViewPager由多个Fragment组成时遇到IllegalStateException的解决方法
- Android:DialogFragment的使用
- ApiDemos--DialogFragment的使用
- DialogFragment的使用示例
- DialogFragment的相关使用
- Dialogfragment的使用
- Android-----DialogFragment的使用
- Android 的线程(AsyncTask、HandlerThread、IntentService详解)和线程池
- 激光雷达与 D1 的坐标校正
- RBAC基于角色的权限控制
- Codeforces 743D Chloe and pleasant prizes 树型dp
- Python下用于监视文件系统的pyinotify包
- DialogFragment使用中show()方法遇到的IllegalStateException
- [kpw] Kindle Paperwhite 升级到 5.6.5 后,kterm无法启动
- Saitama Destroys Hotel CodeForces - 608A
- 微信公众号开发-客户端侧-服务器URL认证 Java版
- php 删除目录,文件
- request.getRequestDispatcher()跳转+中文乱码
- android 常用api 接口签名验证
- uboot编译
- Android 热修复AndFix