onSaveInstanceState()和onRestoreInstanceState() 执行时机和Activity生命周期函数执行顺序

1 onSaveInstanceState()和onRestoreInstanceState()

Activity会在某些特殊情况下被销毁(内存不足,或者不是在主页面调用 Process.killProcess,system.exit()等),然后系统会重新调起Activity。onSaveInstanceState(Bundle outState)和onRestoreInstanceState(Bundle savedInstanceState)用于保存和恢复数据,系统重新恢复被销毁的activity时会读取onSaveInstanceState存储的ui状态信息,恢复原来的界面。

2 onSaveInstanceState()和onRestoreInstanceState()配合源码解释

源码解析:
英文好的可以直接看源码解释,很清楚。

  /**
     * 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).
     *
     这个方法在Activity可能被销毁之前执行,保存状态信息,异常销毁后可以利用这些信息进行恢复。
   
     * <p>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 {@link #onCreate} or {@link #onRestoreInstanceState}.
     *
     不要和activity的生命周期混淆例如onPause,总是被调用在把界面放入后台或者可能被销毁之前(onPause和onStop之间调用)。如果确定Activity会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。 
     * <p>Do not confuse this method with activity lifecycle callbacks such as
     * {@link #onPause}, which is always called when an activity is being placed
     * in the background or on its way to destruction, or {@link #onStop} which
     * is called before destruction.  One example of when {@link #onPause} and
     * {@link #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 {@link #onSaveInstanceState}
     * on B because that particular instance will never be restored, so the
     * system avoids calling it.  An example when {@link #onPause} is called and
     * not {@link #onSaveInstanceState} is when activity B is launched in front of activity A:
     * the system may avoid calling {@link #onSaveInstanceState} 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.
     *
     * <p>The default implementation takes care of most of the UI per-instance
     * state for you by calling {@link android.view.View#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
     * {@link #onRestoreInstanceState}).  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.
     *
     * <p>If called, this method will occur before {@link #onStop}.  There are
     * no guarantees about whether it will occur before or after {@link #onPause}.
     *
     * @param outState Bundle in which to place your saved state.
     *
     * @see #onCreate
     * @see #onRestoreInstanceState
     * @see #onPause
     */
    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);
    }

    /**
     * This is the same as {@link #onSaveInstanceState} but is called for activities
     * created with the attribute {@link android.R.attr#persistableMode} set to
     * <code>persistAcrossReboots</code>. The {@link android.os.PersistableBundle} passed
     * in will be saved and presented in {@link #onCreate(Bundle, PersistableBundle)}
     * the first time that this activity is restarted following the next device reboot.
     *
     * @param outState Bundle in which to place your saved state.
     * @param outPersistentState State which will be saved across reboots.
     *
     * @see #onSaveInstanceState(Bundle)
     * @see #onCreate
     * @see #onRestoreInstanceState(Bundle, PersistableBundle)
     * @see #onPause
     */
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        onSaveInstanceState(outState);
    }

/**
     * This method is called after {@link #onStart} when the activity is
     * being re-initialized from a previously saved state, given here in
     * <var>savedInstanceState</var>.  Most implementations will simply use {@link #onCreate}
     * to restore their state, but it is sometimes convenient to do it here
     * after all of the initialization has been done or to allow subclasses to
     * decide whether to use your default implementation.  The default
     * implementation of this method performs a restore of any view state that
     * had previously been frozen by {@link #onSaveInstanceState}.
     *
     * <p>This method is called between {@link #onStart} and
     * {@link #onPostCreate}.
     *
     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
     *
     * @see #onCreate
     * @see #onPostCreate
     * @see #onResume
     * @see #onSaveInstanceState
     */
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        if (mWindow != null) {
            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
            if (windowState != null) {
                mWindow.restoreHierarchyState(windowState);
            }
        }
    }

onSaveInstanceState一个参数

两个参数的onSaveInstanceState和一个参数的函数类似,这里不做过多概述,可以看源码上的注释。下面讲解的情况都只涉及一个参数的onSaveInstanceState函数。
onSaveInstanceState方法在Activity可能被销毁之前执行,保存状态信息,异常销毁后可以利用这些信息进行恢复。被调用在把界面放入后台或者可能被销毁之前(onPause和onStop之间调用)。如果确定Activity会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。
onSaveInstanceState(Bundle outState)会在以下情况被调用(进入后台,可能被销毁(不是确定会被销毁)):
1、当用户按下HOME键时,屏幕被关闭时。
2、从当前activity启动一个新的activity时。
3、屏幕方向切换时。

onRestoreInstanceState

onRestoreInstanceState(Bundle savedInstanceState)只有在activity确实是被系统回收,重新创建activity的情况下才会被调用,此时参数savedInstanceState一定不为null,在onStart方法之后执行,如果在onRestoreInstanceState中读取savedInstanceState一定有值,如果在onCreate中读取Bundle存储的信息是有可能为null的。

3 onCreate方法里Bundle参数,可以用来恢复数据和onRestoreInstanceState的区别。

onRestoreInstanceState上的注释写的很明白,是可以利用onCreate方法恢复Activity的,所以onCreate中的参数就是执行savedInstanceState后存储的数据。但onCreate方法在savedInstanceState之前执行,savedInstanceState又可能不被执行,所以利用onCreate恢复时需要进行判null处理,但是如果调用了onRestoreInstanceState,参数Bundle一定不为null,可以直接使用参数。

4 savedInstanceState在几种情况下的和生命周期执行的例子

1、当用户按下HOME键时,屏幕被关闭时。
2、从当前activity启动一个新的activity时。
3、屏幕方向切换时。

首先打开新的activity没有执行savedInstanceState。

按下home键:

onPause
onSaveInstanceState
onStop

按下home键后再回来:没有调用savedInstanceState。

关闭屏幕:

onPause
onSaveInstanceState
onStop

关闭屏幕之后回来没有调用。

打开新的Activity:

onPause
onSaveInstanceState
onStop

屏幕方向切换,没有在AndroidManifest.xml中设置configChanges,如果设置了参数由于一定不会被销毁,所以不会调用:

onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onResume

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值