標籤:android activity onsaveinstancestate onrestoreinstancesta
Android Activity的onSaveInstanceState() 和 onRestoreInstanceState()方法:
1. 基本作用:
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:記憶體不足、使用者直接按Home鍵)由系統銷毀一個Activity時,onSaveInstanceState() 會被調用。但是當使用者主動去銷毀一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。因為在這種情況下,使用者的行為決定了不需要儲存Activity的狀態。通常onSaveInstanceState()只適合用於儲存一些臨時性的狀態,而onPause()適合用於資料的持久化儲存。
在activity被殺掉之前調用儲存每個執行個體的狀態,以保證該狀態可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (傳入的Bundle參數是由onSaveInstanceState封裝好的)中恢複。這個方法在一個activity被殺死前調用,當該activity在將來某個時刻回來時可以恢複其先前狀態。
例如,如果activityB啟用後位於activityA的前端,在某個時刻activityA因為系統回收資源的問題要被殺掉,A通過onSaveInstanceState將有機會儲存其使用者介面狀態,使得將來使用者返回到activityA時能通過onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢複介面的狀態。
關於onSaveInstanceState(),是在函數裡面儲存一些View有用的資料到一個Parcelable對象並返回。在Activity的onSaveInstanceState(Bundle outState)中調用View的onSaveInstanceState (),返回Parcelable對象,
接著用Bundle的putParcelable方法儲存在Bundle savedInstanceState中。
當系統調用Activity的的onRestoreInstanceState(Bundle savedInstanceState)時,同過Bundle的getParcelable方法得到Parcelable對象,然後把該Parcelable對象傳給View的onRestoreInstanceState(Parcelable state)。在的View的onRestoreInstanceState中從Parcelable讀取儲存的資料以便View使用。
這就是onSaveInstanceState() 和 onRestoreInstanceState() 兩個函數的基本作用和用法。
2. 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(假定為activityA)顯示在當前task的最上層時,其onSaveInstanceState()方法會在什麼時候被執行,有這麼幾種情況:
(1)、當使用者按下HOME鍵時。
這是顯而易見的,系統不知道你按下HOME後要運行多少其他的程式,自然也不知道activity A是否會被銷毀,因此系統會調用onSaveInstanceState(),讓使用者有機會儲存某些非永久性的資料。以下幾種情況的分析都遵循該原則
(2)、長按HOME鍵,選擇運行其他的程式時。
(3)、按下電源按鍵(關閉螢幕顯示)時。
(4)、從activity A中啟動一個新的activity時。
(5)、螢幕方向切換時,例如從豎屏切換到橫屏時。
在螢幕切換之前,系統會銷毀activity A,在螢幕切換之後系統又會自動地建立activity A,所以onSaveInstanceState()一定會被執行,且也一定會執行onRestoreInstanceState()。
總而言之,onSaveInstanceState()的調用遵循一個重要原則,即當系統存在“未經你許可”時銷毀了我們的activity的可能時,則onSaveInstanceState()會被系統調用,這是系統的責任,因為它必須要提供一個機會讓你儲存你的資料(當然你不儲存那就隨便你了)。如果調用,調用將發生在onPause()或onStop()方法之前。(雖然測試時發現多數在onPause()前)
3. onRestoreInstanceState()什麼時候調用
onRestoreInstanceState()被調用的前提是,activity A“確實”被系統銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調用,例如,當正在顯示activity A的時候,使用者按下HOME鍵回到主介面,然後使用者緊接著又返回到activity A,這種情況下activity A一般不會因為記憶體的原因被系統銷毀,故activity A的onRestoreInstanceState方法不會被執行 此也說明上二者,大多數情況下不成對被使用。
onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調用。
4. onSaveInstanceState()方法的預設實
如果我們沒有覆寫onSaveInstanceState()方法, 此方法的預設實現會自動儲存activity中的某些狀態資料, 比如activity中各種UI控制項的狀態.。android應用程式框架中定義的幾乎所有UI控制項都恰當的實現了onSaveInstanceState()方法,因此當activity被摧毀和重建時, 這些UI控制項會自動儲存和恢複狀態資料. 比如EditText控制項會自動儲存和恢複輸入的資料,而CheckBox控制項會自動儲存和恢複選中狀態.開發人員只需要為這些控制項指定一個唯一的ID(通過設定android:id屬性即可), 剩餘的事情就可以自動完成了.如果沒有為控制項指定ID, 則這個控制項就不會進行自動的資料儲存和恢複操作。
由上所述,如果我們需要覆寫onSaveInstanceState()方法,一般會在第一行代碼中調用該方法的預設實現:super.onSaveInstanceState(outState)。
5. 是否需要重寫onSaveInstanceState()方法
既然該方法的預設實現可以自動的儲存UI控制項的狀態資料, 那什麼時候需要覆寫該方法呢?
如果需要儲存額外的資料時, 就需要覆寫onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只適合儲存瞬態資料, 比如UI控制項的狀態, 成員變數的值等,而不應該用來儲存持久化資料,持久化資料應該當使用者離開當前的 activity時,在 onPause() 中儲存(比如將資料儲存到資料庫或檔案中)。說到這裡,還要說一點的就是在onPause()中不適合用來儲存比較費時的資料,所以這點要理解。
由於onSaveInstanceState()方法方法不一定會被調用, 因此不適合在該方法中儲存持久化資料, 例如向資料庫中插入記錄等. 儲存持久化資料的操作應該放在onPause()中。若是永久性值,則在onPause()中儲存;若大量,則另開線程吧,別阻塞UI線程。
6. 引發activity銷毀和重建的其它情況
除了系統處於記憶體不足的原因會摧毀activity之外, 某些系統設定的改變也會導致activity的摧毀和重建. 例如改變螢幕方向(見上例), 改變裝置語言設定, 鍵盤彈出等。
Android Activity中onSaveInstanceState和onRestoreInstanceState的使用