Android 中onSaveInstanceState()解析

前言

在上一篇文章中,我们分析了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。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值