但是,当系统为了恢复内存而销毁某项 Activity 时,Activity 对象也会被销毁,因此系统在继续 Activity 时根本无法让其状态保持完好,而是必须在用户返回 Activity 时重建 Activity 对象。但用户并不知道系统销毁 Activity 后又对其进行了重建,因此他们很可能认为 Activity 状态毫无变化。 在这种情况下,您可以实现另一个回调方法对有关 Activity 状态的信息进行保存,以确保有关 Activity 状态的重要信息得到保留: onSaveInstanceState()。
系统会先调用 onSaveInstanceState(),然后再使 Activity 变得易于销毁。系统会向该方法传递一个 Bundle,您可以在其中使用 putString() 和 putInt() 等方法以名称-值对形式保存有关 Activity 状态的信息。然后,如果系统终止您的应用进程,并且用户返回您的 Activity,则系统会重建该 Activity,并将Bundle 同时传递给 onCreate()和 onRestoreInstanceState()。您可以使用上述任一方法从 Bundle 提取您保存的状态并恢复该 Activity 状态。如果没有状态信息需要恢复,则传递给您的 Bundle 是空值(如果是首次创建该 Activity,就会出现这种情况)。
此图Activity屏幕转换的时候,未保存数据的状态:
此时没有在相应的回调方法中进行数据保存与恢复,就会导致屏幕的旋转过程中数据的丢失,回调的方法如下:
我们若想保存和恢复数据只需要在对应的方法下进行存取操作即可:
利用Bundle进行存储数据
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data",show.getText().toString());
}
通过Bundle进行取数据:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
show.setText((CharSequence) savedInstanceState.get("data"));
}
效果图如下:
(注意:onSaveInstanceState()方法会在onPause和onStop之间调用,若想保存数据我们需要明确能够走到的生命周期,比如上一篇文章中说到的透明activity就只会走到Onpause,在onpause状态时若被系统干掉,那么就不能保存数据,一般来说保存数据的操作是写在onPause方法中,恢复数据的操作是写在oncreate方法中,这样可以确定被系统回调)
分享一点自己的经验,可能有些小伙伴们写一些UI组件比如Editex或者spinner等,在操作这些组件的时候即使不进行保存操作,系统也会帮我们保存数据,这是因为这些类的父类中定义了此方法:
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
// Save state if we are forced to
final boolean freezesText = getFreezesText();
boolean hasSelection = false;
int start = -1;
int end = -1;
if (mText != null) {
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
hasSelection = true;
}
}
这是TextView中定义的保存的方法返回的是一个parcel对象,它是由freezesText的状态和Id共同决定的,若freezesText的属性为true并且给定Id。那么我们在对此组件进行操作就会自动保存数据,有意思的是,谷歌考虑到用户体验等问题,给Editex的freezsText的属性设置为true且不可更改。因此我们在自定义组件的时候,应该注意这个问题。