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