1. onSaveInstanceState和onRestoreInstanceState基本作用
onSaveInstanceState是用來保存UI狀態(tài)的劈猿,你可以使用它保存你所想保存的東西,在Activity殺死之前庐镐,它一般在onStop或者onPause之前觸發(fā)变逃,onRestoreInstanceState則是在onResume之前觸發(fā)回復(fù)狀態(tài),至于復(fù)寫這個方法后onCreate方法是否會被調(diào)用名眉。
1.Activity被殺死了凰棉,onCreate會被調(diào)用,且onRestoreInstanceState 在 onResume之前恢復(fù)上次保存的信息福压。
2.Activity沒被殺死或舞,onCreate不會被調(diào)用映凳,但onRestoreInstanceState 仍然會被調(diào)用,在 onResume之前恢復(fù)上次保存的信息诈豌。
onSaveInstanceState和onRestoreInstanceState 是一對兄弟矫渔,一個負(fù)責(zé)存儲,一個負(fù)責(zé)取出.“不一定”是成對的被調(diào)用的顿痪。
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法叠聋,它們并不一定會被觸發(fā)。當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足虏束、用戶直接按Home鍵)由系統(tǒng)銷毀一個Activity時镇匀,onSaveInstanceState() 會被調(diào)用袜啃。但是當(dāng)用戶主動去銷毀一個Activity時,例如在應(yīng)用中按返回鍵晰韵,onSaveInstanceState()就不會被調(diào)用熟妓。因為在這種情況下,用戶的行為決定了不需要保存Activity的狀態(tài)只恨。通常onSaveInstanceState()只適合用于保存一些臨時性的狀態(tài)抬虽,而onPause()適合用于數(shù)據(jù)的持久化保存。
在activity被殺掉之前調(diào)用保存每個實例的狀態(tài),以保證該狀態(tài)可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (傳入的Bundle參數(shù)是由onSaveInstanceState封裝好的)中恢復(fù)缰猴。這個方法在一個activity被殺死前調(diào)用疤剑,當(dāng)該activity在將來某個時刻回來時可以恢復(fù)其先前狀態(tài)隘膘。
例如,如果activity B啟用后位于activity A的前端弯菊,在某個時刻activity A因為系統(tǒng)回收資源的問題要被殺掉,A通過onSaveInstanceState將有機(jī)會保存其用戶界面狀態(tài)钦铁,使得將來用戶返回到activity A時能通過onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢復(fù)界面的狀態(tài)牛曹。
關(guān)于onSaveInstanceState (),是在函數(shù)里面保存一些View有用的數(shù)據(jù)到一個Parcelable對象并返回超营。在Activity的onSaveInstanceState(Bundle outState)中調(diào)用View的onSaveInstanceState ()阅虫,返回Parcelable對象,
接著用Bundle的putParcelable方法保存在BundlesavedInstanceState中米碰。
當(dāng)系統(tǒng)調(diào)用Activity的的onRestoreInstanceState(Bundle savedInstanceState)時购城,同過Bundle的getParcelable方法得到Parcelable對象工猜,然后把該Parcelable對象傳給View的onRestoreInstanceState (Parcelable state)。在的View的onRestoreInstanceState中從Parcelable讀取保存的數(shù)據(jù)以便View使用史侣。
這就是onSaveInstanceState() 和onRestoreInstanceState() 兩個函數(shù)的基本作用和用法魏身。
2. onSaveInstanceState() 什么時候調(diào)用
先看Application Fundamentals上的一段話:
Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
從這句話可以知道箭昵,當(dāng)某個activity變得“容易”被系統(tǒng)銷毀時,該activity的onSaveInstanceState就會被執(zhí)行正林,除非該activity是被用戶主動銷毀的颤殴,例如當(dāng)用戶按BACK鍵的時候。
注意上面的雙引號杈绸,何為“容易”?言下之意就是該activity還沒有被銷毀塑娇,而僅僅是一種可能性劫侧。這種可能性有哪些?通過重寫一個activity的所有生命周期的onXXX方法奇瘦,包括onSaveInstanceState和onRestoreInstanceState方法劲弦,我們可以清楚地知道當(dāng)某個activity(假定為activity A)顯示在當(dāng)前task的最上層時邑跪,其onSaveInstanceState方法會在什么時候被執(zhí)行呼猪,有這么幾種情況:
1、當(dāng)用戶按下HOME鍵時
這是顯而易見的轴踱,系統(tǒng)不知道你按下HOME后要運行多少其他的程序谚赎,自然也不知道activity A是否會被銷毀壶唤,故系統(tǒng)會調(diào)用onSaveInstanceState,讓用戶有機(jī)會保存某些非永久性的數(shù)據(jù)悯辙。以下幾種情況的分析都遵循該原則
2迎吵、長按HOME鍵,選擇運行其他的程序時茴肥。
3荡灾、按下電源按鍵(關(guān)閉屏幕顯示)時瞬铸。
4嗓节、從activity A中啟動一個新的activity時皆警。
5、屏幕方向切換時鸵隧,例如從豎屏切換到橫屏?xí)r
在屏幕切換之前豆瘫,系統(tǒng)會銷毀activity A菊值,在屏幕切換之后系統(tǒng)又會自動地創(chuàng)建activity A,所以onSaveInstanceState一定會被執(zhí)行
總而言之腻窒,onSaveInstanceState的調(diào)用遵循一個重要原則昵宇,即當(dāng)系統(tǒng)“未經(jīng)你許可”時銷毀了你的activity,則onSaveInstanceState會被系統(tǒng)調(diào)用儿子,這是系統(tǒng)的責(zé)任瓦哎,因為它必須要提供一個機(jī)會讓你保存你的數(shù)據(jù)(當(dāng)然你不保存那就隨便你了)。
3. onRestoreInstanceState()什么時候調(diào)用
至于onRestoreInstanceState方法柔逼,需要注意的是蒋譬,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成對的被調(diào)用的。
onRestoreInstanceState被調(diào)用的前提是卒落,activity A“確實”被系統(tǒng)銷毀了羡铲,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調(diào)用儡毕,例如,當(dāng)正在顯示activity A的時候腰湾,用戶按下HOME鍵回到主界面雷恃,然后用戶緊接著又返回到activity A,這種情況下activity A一般不會因為內(nèi)存的原因被系統(tǒng)銷毀费坊,故activity A的onRestoreInstanceState方法不會被執(zhí)行.此處也說明以上二者倒槐,大多數(shù)情況下不成對被使用。
另外附井,onRestoreInstanceState的bundle參數(shù)也會傳遞到onCreate方法中讨越,你也可以選擇在onCreate方法中做數(shù)據(jù)還原.
onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調(diào)用两残。
4. onSaveInstanceState()方法的默認(rèn)實現(xiàn)
如果我們沒有覆寫onSaveInstanceState()方法, 此方法的默認(rèn)實現(xiàn)會自動保存activity中的某些狀態(tài)數(shù)據(jù), 比如activity中各種UI控件的狀態(tài).。android應(yīng)用框架中定義的幾乎所有UI控件都恰當(dāng)?shù)膶崿F(xiàn)了onSaveInstanceState()方法,因此當(dāng)activity被摧毀和重建時, 這些UI控件會自動保存和恢復(fù)狀態(tài)數(shù)據(jù). 比如EditText控件會自動保存和恢復(fù)輸入的數(shù)據(jù),而CheckBox控件會自動保存和恢復(fù)選中狀態(tài).開發(fā)者只需要為這些控件指定一個唯一的ID(通過設(shè)置android:id屬性即可), 剩余的事情就可以自動完成了.如果沒有為控件指定ID, 則這個控件就不會進(jìn)行自動的數(shù)據(jù)保存和恢復(fù)操作把跨。
由上所述, 如果我們需要覆寫onSaveInstanceState()方法, 一般會在第一行代碼中調(diào)用該方法的默認(rèn)實現(xiàn):super.onSaveInstanceState(outState)人弓。
5. 是否需要重寫onSaveInstanceState()方法
既然該方法的默認(rèn)實現(xiàn)可以自動的保存UI控件的狀態(tài)數(shù)據(jù), 那什么時候需要覆寫該方法呢?
如果需要保存額外的數(shù)據(jù)時, 就需要覆寫onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只適合保存瞬態(tài)數(shù)據(jù), 比如UI控件的狀態(tài), 成員變量的值等着逐,而不應(yīng)該用來保存持久化數(shù)據(jù)崔赌,持久化數(shù)據(jù)應(yīng)該當(dāng)用戶離開當(dāng)前的activity時,在onPause()中保存(比如將數(shù)據(jù)保存到數(shù)據(jù)庫或文件中)耸别。說到這里健芭,還要說一點的就是在onPause()中不適合用來保存比較費時的數(shù)據(jù),所以這點要理解秀姐。
由于onSaveInstanceState()方法方法不一定會被調(diào)用, 因此不適合在該方法中保存持久化數(shù)據(jù), 例如向數(shù)據(jù)庫中插入記錄等. 保存持久化數(shù)據(jù)的操作應(yīng)該放在onPause()中慈迈。若是永久性值,則在onPause()中保存囊扳;若大量吩翻,則另開線程吧兜看,別阻塞UI線程锥咸。
6. 引發(fā)activity銷毀和重建的其它情況
除了系統(tǒng)處于內(nèi)存不足的原因會摧毀activity之外, 某些系統(tǒng)設(shè)置的改變也會導(dǎo)致activity的摧毀和重建. 例如改變屏幕方向(見上例), 改變設(shè)備語言設(shè)定, 鍵盤彈出等。
另外细移,當(dāng)屏幕的方向發(fā)生了改變搏予, Activity會被摧毀并且被重新創(chuàng)建,如果你想在Activity被摧毀前緩存一些數(shù)據(jù)弧轧,并且在Activity被重新創(chuàng)建后恢復(fù)緩存的數(shù)據(jù)雪侥。