Can not perform this action after onSaveInstanceState异常源码分析
来源:互联网 发布:用homebrew安装mysql 编辑:程序博客网 时间:2024/06/04 20:03
转载请标明来源:http://blog.csdn.net/rflyee/article/details/74719551
异常如下:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
在使用fragment、dialogFragment等控件时可能会遇到以上异常。原因正如抛出的异常所说一样:不能在onSaveInstanceState之后执行该操作。即不能执行commit()操作,包括dialogFragment的show()、dismiss(),fragment中fragmentTransaction的commit()等等。
接下来,找一下崩溃源码,追一下崩溃相关的源码流程。
对应的崩溃源码流程:
比如调用DialogFragment#show()
public void show(FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); // 这里这里}
commit的实现方法:
@Overridepublic int commit() { return commitInternal(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;}
最终到了FragmentManager中,接着看enqueueAction方法
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); } }}private void checkStateLoss() { if (mStateSaved) { // 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); }}
从整个流程中看到,只要在commit时,mStateSaved已经被置为true,则会抛出该异常。
那么问题来了,都有哪些方法会保存状态,也就是把mStateSaved置为true呢?
- onSaveInstanceState
既然异常中说了和onSaveInstanceState方法有关,那么就先看看该方法做了什么:
Activity.java(android-22)
/** * Called to retrieve per-instance state from an activity before being killed * so that the state can be restored in {@link #onCreate} or * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method * will be passed to both). * ........... 这里省略的说明对理解onSaveInstanceState很重要,有点多,自己去看吧 */protected void onSaveInstanceState(Bundle outState) { // 保存window的Hierarchy状态 outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState()); // 保存fragment的状态。如果感兴趣可以再看看mFragments.saveAllState()的实现,也是保存状态 Parcelable p = mFragments.saveAllState(); if (p != null) { outState.putParcelable(FRAGMENTS_TAG, p); } getApplication().dispatchActivitySaveInstanceState(this, outState);}
FragmentActivity.java(android-22)
/** * Save all appropriate fragment state. */@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState); Parcelable p = mFragments.saveAllState(); if (p != null) { outState.putParcelable(FRAGMENTS_TAG, p); }}
可以继续跟下 mFragments.saveAllState(),
Parcelable saveAllState() { // Make sure all pending operations have now been executed to get // our state update-to-date. execPendingActions(); if (HONEYCOMB) { // 这个解释也可以好好看看,说明了不同版本保存状态的时机是不同的 // As of Honeycomb, we save state after pausing. Prior to that // it is before pausing. With fragments this is an issue, since // there are many things you may do after pausing but before // stopping that change the fragment state. For those older // devices, we will not at this point say that we have saved // the state, so we will allow them to continue doing fragment // transactions. This retains the same semantics as Honeycomb, // though you do have the risk of losing the very most recent state // if the process is killed... we'll live with that. mStateSaved = true; // 在这里保存了 } ....省略....}
- 另外,可以再看看FragmentActivity#onStop()方法:
@Overrideprotected void onStop() { super.onStop(); mStopped = true; mHandler.sendEmptyMessage(MSG_REALLY_STOPPED); mFragments.dispatchStop();}
继续追继续追,最后也是到FragmentManager中
public void dispatchStop() { // See saveAllState() for the explanation of this. We do this for // all platform versions, to keep our behavior more consistent between // them. mStateSaved = true; // 这里这里 moveToState(Fragment.STOPPED, false);}
是的,yeke直接看FragmentManager中mStateSaved的变化时机就可以了,比如下边几个,更详细的跟下源码即可:
public void noteStateNotSaved() { mStateSaved = false; // 这里}public void dispatchCreate() { mStateSaved = false; // 这里 moveToState(Fragment.CREATED, false);}public void dispatchActivityCreated() { mStateSaved = false; // 这里 moveToState(Fragment.ACTIVITY_CREATED, false);}public void dispatchStart() { mStateSaved = false; // 这里 moveToState(Fragment.STARTED, false);}public void dispatchResume() { mStateSaved = false; // 这里 moveToState(Fragment.RESUMED, false);}public void dispatchPause() { moveToState(Fragment.STARTED, false);}public void dispatchStop() { // See saveAllState() for the explanation of this. We do this for // all platform versions, to keep our behavior more consistent between // them. mStateSaved = true; // 这里 moveToState(Fragment.STOPPED, false);}
目前为止,基本了解了该异常的抛出相关的源码流程了。
下篇博客这里这里继续分析下如何避免该异常,以及其他相关细节。
转载请标明来源:http://blog.csdn.net/rflyee/article/details/74719551
- Can not perform this action after onSaveInstanceState异常源码分析
- Android 异常 IllegalStateException: Can not perform this action after onSaveInstanceState
- 解决异常IllegalStateException: Can not perform this action after onSaveInstanceState
- fragment 异常IllegalStateException: Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState(fragment异常)
- can not perform this action after onsaveinstancestate异常
- android异常:Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState 异常
- fragment/dialogfragment异常:Can not perform this action after onSaveInstanceState
- Android-异常处理-Can not perform this action after onSaveInstanceState
- IllegalStateException: Can not perform this action after onSaveInstanceState 异常解决
- 解决Can not perform this action after onSaveInstanceState异常总结
- Fragment异常:Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState
- Can not perform this action after onSaveInstanceState
- PHP mktime() 创建日期
- 详解Nginx与Apache共用80端口的配置方法
- 人脸检测——准备非人脸
- Glide如何加载https图片(简明操作)
- 使用js获取到css3的兼容前缀
- Can not perform this action after onSaveInstanceState异常源码分析
- Amazon Athena 性能调整
- BZOJ 1663: [Usaco2006 Open]赶集 floyd(划掉+dp
- Spring MVC数据转换、格式化、校验、文件上传和下载
- 测试
- Java & Pascal & C++——容斥原理例题——切蛋糕
- 如何防止Edit框中的Password不被非法获取
- Linux小知识
- [spring cloud学习5]使用docker发布spring cloud应用