onSaveInstanceState和onRestoreInstanceState詳解

路過的坑總結下纔不會又踏進去 mark下

一. 作用 Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷燬 一個Activity時,onSaveInstanceState() 會被調用。但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。因爲在這種情 況下,用戶的行爲決定了不需要保存Activity的狀態。通常onSaveInstanceState()只適合用於保存一些臨時性的狀態,而 onPause()適合用於數據的持久化保存。 在activity被殺掉之前調用保存每個實例的狀態,以保證該狀態可以在 onCreate(Bundle)或者onRestoreInstanceState(Bundle) (傳入的Bundle參數是由onSaveInstanceState封裝好的)中恢復。這個方法在一個activity被殺死前調用,當該 activity在將來某個時刻回來時可以恢復其先前狀態。

例如,如果activity B啓用後位於activity A的前端,在某個時刻activity A因爲系統回收資源的問題要被殺掉,A通過onSaveInstanceState將有機會保存其用戶界面狀態,使得將來用戶返回到activity A時能通過onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢復界面的狀態。

這就是onSaveInstanceState() 和 onRestoreInstanceState() 兩個函數的基本作用和用法。(ps:關於原理實現請追尋源碼,就是view的保存與繪製) 二. onSaveInstanceState的調用時機 當某個activity變得“容易”被系統銷燬時,該activity的onSaveInstanceState就會被執行,除非該activity是被用戶主動銷燬的,例如當用戶按BACK鍵的時候。 注意上面的雙引號,何爲"容易"?意思就是說該activity還沒有被銷燬,而僅僅是一種可能性。這 種可能性有哪些?通過重寫一個activity的所有生命週期的onXXX方法,包括onSaveInstanceState()和 onRestoreInstanceState() 方法,我們可以清楚地知道當某個activity(假定爲activity A)顯示在當前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()前)

三. onRestoreInstanceState()調用時機 onRestoreInstanceState() 被調用的前提是,activity A“確實”被系統銷燬了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調用,例如,當正在顯示activity A的時候,用戶按下HOME鍵回到主界面,然後用戶緊接着又返回到activity A,這種情況下activity A一般不會因爲內存的原因被系統銷燬,故activity A的onRestoreInstanceState方法不會被執行 此也說明上二者,大多數情況下不成對被使用。 onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調用。 四. onSaveInstanceState()方法的默認實現    如果我們沒有覆寫onSaveInstanceState()方法, 此方法的默認實現會自動保存activity中的某些狀態數據, 比如activity中各種UI控件的狀態.。android應用框架中定義的幾乎所有UI控件都恰當的實現了 onSaveInstanceState()方法,因此當activity被摧毀和重建時, 這些UI控件會自動保存和恢復狀態數據. 比如EditText控件會自動保存和恢復輸入的數據,而CheckBox控件會自動保存和恢復選中狀態.開發者只需要爲這些控件指定一個唯一的ID(通 過設置android:id屬性即可), 剩餘的事情就可以自動完成了.如果沒有爲控件指定ID, 則這個控件就不會進行自動的數據保存和恢復操作。

  由上所述, 如果我們需要覆寫onSaveInstanceState()方法, 一般會在第一行代碼中調用該方法的默認實現:super.onSaveInstanceState(outState)。 五. 是否需要重寫onSaveInstanceState()方法   既然該方法的默認實現可以自動的保存UI控件的狀態數據, 那什麼時候需要覆寫該方法呢?

  如果需要保存額外的數據時, 就需要覆寫onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只適合保存瞬態數據, 比如UI控件的狀態, 成員變量的值等,而不應該用來保存持久化數據,持久化數據應該當用戶離開當前的 activity時,在 onPause() 中保存(比如將數據保存到數據庫或文件中)。說到這裏,還要說一點的就是在onPause()中不適合用來保存比較費時的數據,所以這點要理解。

  由於onSaveInstanceState()方法方法不一定會被調用, 因此不適合在該方法中保存持久化數據, 例如向數據庫中插入記錄等. 保存持久化數據的操作應該放在onPause()中。若是永久性值,則在onPause()中保存;若大量,則另開線程吧,別阻塞UI線程。

六. 引發activity銷燬和重建的其它情況   除了系統處於內存不足的原因會摧毀activity之外, 某些系統設置的改變也會導致activity的摧毀和重建. 例如改變屏幕方向(見上例), 改變設備語言設定, 鍵盤彈出等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章