Activity在非正常行为下的数据保存和恢复
onSaveInstanceState
今天同举在移植CPActivity到印尼钱包的时候遇到了一个数据保存的问题,这里简单了解了一下。
比如我们要做一个游戏软件,如果 Activity 当前被停止或长期未使用(比如用户离开了),或者游戏被压到后台了,前台Activity需要更多资源以致系统必须关闭后台进程恢复内存,Activity也可能被系统销毁。在这种「非正常应用行为」结束的情况下,已经被销毁的Activity实例在用户重新打开Activity的时候会被恢复。
有一个回调方法叫作 onSaveInstanceState()
,Activity开始停止时系统会调用它。如果你使用这个回调方法然后什么都不做的话,那么系统会在Bundle里为你保存Activity布局。比如你已经在EditText
里输入了文字了,Activity恢复的时候这些文字也会恢复。如果你想保存其他东西,也可以往Bundle里添加:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
//...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
复制代码
然后在恢复的时候,可以选择两种方式:
- onCreate()
- onRestoreInstanceState()
使用onCreate()的话,需要判断savedInstanceState是否为空,比如对于上面的游戏的例子,恢复用户的得分和等级:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
//...
}
复制代码
更具体的,在JDRActivity里,我们看到如果传进来的bundle为空,就初始化uidata,否则就获取保存在bundle中的uidata:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
mUIData = initUIData();
} else {
savedInstanceState.setClassLoader(getClass().getClassLoader());
mUIData = (UIData) savedInstanceState.getSerializable(UIDATA);
postRestoreUIData(savedInstanceState);
}
//更多操作...
//...
}
复制代码
也可以使用 onRestoreInstanceState()
这个回调方法,这个方法在onStart
之后,onCreate
之前。这种情况下不需要判断savedInstanceState是否为空,因为只有不为空的时候系统才会调用这个。
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
复制代码
persistAcrossReboots
有一个有趣的新特性,可以实现关机后数据保存。在API 21之后,如果在Manifest中加入:
android:persistableMode="persistAcrossReboots"
复制代码
现在,下面三个方法中中,都添加了这样的一个新的Bundle:
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState)
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState)
复制代码
这个Bundle用来保存关机后的数据(我猜的,没有验证过)。
Reference:
[1]https://developer.android.com/training/basics/activity-lifecycle/recreating.html
[2]https://developer.android.com/guide/components/activities.html
[3]http://blog.csdn.net/lincyang/article/details/45287599