前言

在上一篇文章中,我们分析了Fragment中出现Can not perform this action after onSaveInstanceState的异常。里面提到了不能在onSaveInstanceState之后,进行commit的操作。下面将对Activity中的onSaveInstanceState方法进行说明。
在Android api文档中,针对该方法有这么一段描述(简略):
This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via onCreate(Bundle) or onRestoreInstanceState(Bundle).
上面大致意思是,onSaveInstanceState方法是在activity将要被kill的时候执行,这样的话将来某个时候能够恢复它的状态。例如,A页面上启动B页面,在某一时刻A被kill来回收资源,A将会有一个机会通过这个方法来保存当前界面的状态,这样的话,当用户返回到A页面时,用户界面的状态能够通过onCreate和onRestoreInstanceState方法来恢复。
不要将onSaveInstanceState方法与activity中的生命周期回调方法混淆,如:onPause(),当一个activity被放在后台运行或者被销毁时,经常被调用,而它却不一定。
这里有一个例子,当onPause()和onStop()被调用后,而onSaveInstanceState不被被调用:用户在B页面使用back键回到A页面,这里就不需要调用B页面的onSaveInstanceState方法,因为这个B页面这个实例永远不会被恢复,因此系统避免调用这个方法。

什么时候执行onSaveInstanceState

1.从activity A中启动一个新的activity时;
2.屏幕方向切换时,例如从竖屏切换到横屏时;
注意:在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
3.按下电源按键(关闭屏幕显示)时;
4.当用户按下HOME键,回到桌面时。

总之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据,主动finish activity 时,不会调用该方法。另外,onSaveInstanceState()会在onPause()或onStop()之前执行,onRestoreInstanceState()会在onStart()和onResume()之间执行。

源码解析

在项目中,我继承的是AppCompatActivity类,可以从该类中查看onSaveInstanceState方法的执行

    @Override    protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        getDelegate().onSaveInstanceState(outState);    }

而AppCompatActivity类又是继承FragmentActivity,继续查看父类的方法,如下:

    /**     * Save all appropriate fragment state.     */    @Override    protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        Parcelable p = mFragments.saveAllState();        if (p != null) {            outState.putParcelable(FRAGMENTS_TAG, p);        }        if (mPendingFragmentActivityResults.size() > 0) {            outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);            int[] requestCodes = new int[mPendingFragmentActivityResults.size()];            String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];            for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {                requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);                fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);            }            outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);            outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);        }    }

从方法内部可以看到,里面执行了saveAllState(),这个方法控制了FragmentManager中的mStateSaved = true。具体可以看之前的文章。然后,在outState中保存了一些Fragment中的信息。
继续查看Activity中的onSaveInstanceState方法,如下:

protected void onSaveInstanceState(Bundle outState) {    outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());    Parcelable p = mFragments.saveAllState();    if (p != null) {        outState.putParcelable(FRAGMENTS_TAG, p);    }    getApplication().dispatchActivitySaveInstanceState(this, outState);}

里面同样执行了saveAllState()的方法,还有saveHierarchyState()方法。而saveHierarchyState()方法中,保存了Window 的 HierarchyState,主要是UI的层级状态,包括id等一些信息。

总结
屏幕方向切换时,Activity被系统销毁后重新建立,此时会调用onSaveInstanceState方法保存数据。方法执行过程为:
onPause –>onSaveInstanceState–>onStop–>onDestory–>onCreate(切换屏幕后重新创建Activity时调用的onCreate方法)–>onStart–>onRestoryInstanceState–>onResume。

更多相关文章

  1. Android之back键拦截处理
  2. Android全屏与非全屏问题
  3. 【基于zxing的编解码实战】zxing项目源码解读(2.3.0版本,Android部
  4. Android(安卓)Scripting Environment动手玩
  5. android 执行monkey指令的方法
  6. Android(安卓)音乐播放器
  7. Android(安卓)Camera调用流程
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. Android DownloadManager下载并安装apk
  2. Android(安卓)O热点hostapd.conf配置文件
  3. Android学习札记36:一个关于onSaveInstanc
  4. Android RecyclerView 报错:java.lang.Ill
  5. android 图片灰度处理的处理
  6. Android完美禁用Home键
  7. Android处理scrollciew里嵌套ExpandableL
  8. 轮播网络图片加载适配
  9. android之RadioButton设置setChecked(tru
  10. android闹钟(五):实现闹钟功能