Android onSaveInstanceState调用时机

本文详细介绍了Android中onSaveInstanceState方法的作用和调用时机,它用于在activity被销毁前保存状态,以便在activity恢复时使用onCreate或onRestoreInstanceState恢复。通常在onStop之后(Android P及更高版本)或onPause之前(目标SDK小于11)调用。文章还通过源码分析验证了调用顺序,并讨论了不同场景下的调用条件。
摘要由CSDN通过智能技术生成

onSaveInstanceState介绍

首先看一下onSaveInstanceState
官方API介绍(需要翻墙)。

Called to retrieve per-instance state from an activity before being killed so that the state can be restored in onCreate(Bundle) or onRestoreInstanceState(Bundle) (the Bundle populated by this method will be passed to both).

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).

Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn’t killed during the lifetime of B since the state of the user interface of A will stay intact.

The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)). If you override this method to save additional information not captured by each individual view, you will likely want to call through to the default implementation, otherwise be prepared to save all of the state of each view yourself.

If called, this method will occur after onStop() for applications targeting platforms starting with P. For applications targeting earlier platform versions this method will occur before onStop() and there are no guarantees about whether it will occur before or after onPause().

介绍有点长,我翻译了一下:

在activity被销毁之前,该方法会被调用,用来存储每个实例的状态。这些信息存储在Bundle中,通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)方法恢复实例的状态。

这个方法会在activity可能被销毁之前调用,如果将来activity回到了前台,就可以恢复它的状态。举个例子,如果activity A打开了Activity B,那么就有可能为了回收资源而导致Acitvity A被销毁,鉴于有这种情况出现,那么为了能让用户在将来再次回到Acitivty A时仍然能够看到之前的交互信息,就会调用onSaveInstanceState方法保存activity的状态。通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)方法恢复实例的的状态。

不要把这个方法与activity生命周期中的一些方法混淆了,onPause()会在acitivity且后台的时候被调用。什么时候onPause和onStop会调用,但是onSaveInstanceState不会调用呢?举个例子,当从Activity B回到Activity A后,由于B的状态不需要保存了,所以系统就不会调用onSaveInstanceState方法了。什么时候onPause会调用但是onSaveInstanceState不会调用呢?当Activity A上打开了Activity B后,如果A在B的生命周期内不会被销毁,那么A就不会调用onSaveInstanceState方法,A的用户交互信息仍将保持完整性。

该方法的默认实现存储了大部分UI的状态,存储了每个view及其对应的id(通过onRestoreInstanceState的默认实现可以将存储的信息恢复出来)。如果你覆盖了这个方法,想在这个方法里额外添加一些信息,那么最好调用下默认实现(super. onSaveInstanseState),否则你就要自己来手动存储所有view的状态了。
从android P开始,这个方法将在onStop()之后被调用。对于版本较低的系统,这个方法将在onStop之前调用,无法保证与onPause的先后调用顺序。

虽然这段内容很长,但是都是满满的干货。大部分也都很好理解,不过我对下面这句话一直存在疑问,

An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn’t killed during the lifetime of B since the state of the user interface of A will stay intact.

Activity A打开了Activity B,真的可以保证Activity A在Activity B的生命周期内绝对不会被杀吗?如何绝对保证呢?如果无法保证,那么就一定会调用onSaveInstanceState吧。

简单来说,onSaveInstanceState作用就是在activity可能被销毁时被调用来存储activity的状态,然后可以在onCreate或者onRestoreInstanceState中恢复这些信息。

其实上面的介绍已经比较详细的说明了这个方法的调用时机,即:

从android P开始,这个方法将在onStop()之后被调用。对于版本较低的系统,这个方法将在onStop之前调用,无法保证与onPause的先后调用顺序。

onSaveInstanceState调用时机源码分析

我们现在从源码的角度验证这一观点。我们验证的版本是Android 8.0(API 26):

首先我们看下Activity.java中的onSaveInstanceState方法定义:

    // Activity.java
    protected void onSaveInstanceState(Bundle outState) {
   
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

        outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
   
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        if (mAutoFillResetNeeded) {
   
            outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
            getAutofillManager().onSaveInstanceState(outState);
        }
        getApplication().dispatchActivitySaveInstanceState(this, outState);
    }

从这个方法我们大概可以看到onSaveInstanceState这个方法保存了ui的信息和fragment的状态。那么我们看下activity
中调用该方法的地方:

    // Activity.java
    final void performSaveInstanceState(Bundle outState) {
   
        onSaveInstanceState
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值