Activity 緩存方法
我們知道在Activity 的onCreate方法有都有一個Bundle savedInstanceState對象,而Bundle 這個在API里的定義是:A mapping from String keys to various {@link Parcelable} values. 是一個map對象。
所以Activity里緩存的方法要從Bundle 入手,在Activity 提供兩個方法,用于緩存和取緩存。onSaveInstanceState(Bundle outState),onRestoreInstanceState(Bundle savedInstanceState)。
作用
Activity 的onSaveInstanceState和onRestoreInstanceState 并不是和onCreate()、onStart()等生命周期方法一樣,按一定順序執行。這兩個方法不一定每次都會執行,它們只有在特定情況下才會觸發。比如當應用可能發生意外情況(如:內存不足,旋轉屏幕,按下Home,長按Home啟動其他應用等)被系統銷毀Activity時會觸發onSaveInstanceState。如果當用戶主動去銷毀Activity時,是不會被調用的。所以通常情況下onSaveInstanceState只適合保存一些臨時的狀態,而onPause()適合用于數據的持久化保存。
onSaveInstanceState
先看Application Fundamentals上的一段話:
? Android calls onSaveInstanceState() before the activitybecomes vulnerable to being destroyed by the system, but does not bothercalling it when the instance is actually being destroyed by a user action (suchas pressing the BACK key).
從這句話可以知道,當某個activity變得"容易"被系統銷毀時,該activity的onSaveInstanceState()就會被執行,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵的時候。
注意上面的雙引號,何為"容易"?意思就是說該activity還沒有被銷毀,而僅僅是一種可能性。這種可能性有哪些?通過重寫一個activity的所有生命周期的onXXX方法,包括onSaveInstanceState()和onRestoreInstanceState() 方法,我們可以清楚地知道當某個activity(假定為activity A)顯示在當前task的最上層時,其onSaveInstanceState()方法會在什么時候被執行,有這么幾種情況:
-
當用戶按下HOME鍵時。
這是顯而易見的,系統不知道你按下HOME后要運行多少其他的程序,自然也不知道activity A是否會被銷毀,因此系統會調用onSaveInstanceState(),讓用戶有機會保存某些非永久性的數據。
長按HOME鍵,選擇運行其他的程序時。
按下電源按鍵(關閉屏幕顯示)時。
從activity A中啟動一個新的activity時。
屏幕方向切換時,例如從豎屏切換到橫屏時。
注意:
- 在onSaveInstanceState 方法里面一般我們默認實現super.onSaveInstanceState(outState);此方法會默認自動保存Activity的UI狀態,比如Edittext輸入的值會恢復,而CheckBox控件會自動保存復選狀態。這里有一個條件,就是要為這些控件指定唯一的Id,即通過設置android:id屬性即可。剩余的事就交給onSaveInstanceState 自動完成。
- 由于onSaveInstanceState 只會保存跟UI有關的狀態數據,那我們什么時候需要復寫這個方法?我們在需要保存額外的數據時, 就需要覆寫onSaveInstanceState()方法。****
- onSaveInstanceState()方法調用不確定性,所以只適合保存瞬態數據, 比如UI控件的狀態, 成員變量的值等,不能用來保存持久化的數據。持久化數據應該當用戶離開當前的 activity時,在 onPause() 中保存(比如將數據保存到數據庫或文件中)
onRestoreInstanceState
onRestoreInstanceState 和 onSaveInstanceState 并不是成對出現的,有時候在調用onSaveInstanceState 并沒有出現onRestoreInstanceState的調用。比如我們按下home鍵返回到桌面時,此時馬上又回到原來的應用Activity,onRestoreInstanceState就沒有被調用,因為此時的Activity并沒有被銷毀,所以onRestoreInstanceState就沒有被調用。
onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調用。這個調用順序要注意。
代碼:
public class InstanceStateActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogHelper.i("*****onCreate()方法******");
LogHelper.i( "onCreate:" + getClass().getSimpleName() + " TaskId: " + getTaskId() + " hasCode:" + this.hashCode());
setContentView(R.layout.test_standar_activity);
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(InstanceStateActivity.this,StandardActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onRestart() {
super.onRestart();
LogHelper.i("*****onRestart()方法******");
}
@Override
protected void onStart() {
super.onStart();
LogHelper.i("*****onStart()方法******");
}
@Override
protected void onResume() {
super.onResume();
LogHelper.i("*****onResume()方法******");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("testBoolean", true);
outState.putDouble("testDouble", 2.0);
outState.putInt("testInt", 1);
outState.putString("testString", "Test Android");
LogHelper.i("*****onSaveInstanceState()方法******");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
boolean testBoolean = savedInstanceState.getBoolean("testBoolean");
double testDouble = savedInstanceState.getDouble("testDouble");
int testInt = savedInstanceState.getInt("testInt");
String testString = savedInstanceState.getString("testString");
LogHelper.i("*****onRestoreInstanceState()方法******");
LogHelper.i("*****testBoolean "+testBoolean+", testDouble "+testDouble+", testInt "+testInt+", testString "+testString);
}
}