淺析Activity的onSaveInstanceState() 和,onRestoreInstanceState(),onPause

橫豎屏切換:

onStart→onResume→onSaveInstanceState→onPause→onStop→onStart→onRestoreInstanceState→onResume

按Home鍵回到桌面烫堤,清內(nèi)存后回來程序

onResume→onSaveInstanceState→onPause→onStop→onStart →onResume

1.?基本作用:

  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)用。因?yàn)樵谶@種情況下氛改,用戶的行為決定了不需要保存Activity的狀態(tài)帐萎。通常onSaveInstanceState()只適合用于保存一些臨時性的狀態(tài),而onPause()適合用于數(shù)據(jù)的持久化保存胜卤。

  在activity被殺掉之前調(diào)用保存每個實(shí)例的狀態(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因?yàn)橄到y(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方法保存在Bundle ?savedInstanceState中鹦聪。

  當(dāng)系統(tǒng)調(diào)用Activity的的onRestoreInstanceState(Bundle savedInstanceState)時,?同過Bundle的getParcelable方法得到Parcelable對象蒂秘,然后把該P(yáng)arcelable對象傳給View的onRestoreInstanceState (Parcelable state)泽本。在的View的onRestoreInstanceState中從Parcelable讀取保存的數(shù)據(jù)以便View使用。

  這就是onSaveInstanceState() 和?onRestoreInstanceState() 兩個函數(shù)的基本作用和用法姻僧。

2.?onSaveInstanceState() 什么時候調(diào)用

  先看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).

  從這句話可以知道规丽,當(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后要運(yùn)行多少其他的程序棘脐,自然也不知道activity A是否會被銷毀斜筐,因此系統(tǒng)會調(diào)用onSaveInstanceState(),讓用戶有機(jī)會保存某些非永久性的數(shù)據(jù)蛀缝。以下幾種情況的分析都遵循該原則

  (2)顷链、長按HOME鍵,選擇運(yùn)行其他的程序時屈梁。

  (3)嗤练、按下電源按鍵(關(guān)閉屏幕顯示)時。

  (4)在讶、從activity A中啟動一個新的activity時煞抬。

  (5)、屏幕方向切換時构哺,例如從豎屏切換到橫屏?xí)r此疹。

  在屏幕切換之前,系統(tǒng)會銷毀activity A遮婶,在屏幕切換之后系統(tǒng)又會自動地創(chuàng)建activity A蝗碎,所以onSaveInstanceState()一定會被執(zhí)行,且也一定會執(zhí)行onRestoreInstanceState()旗扑。

  總而言之蹦骑,onSaveInstanceState()的調(diào)用遵循一個重要原則,即當(dāng)系統(tǒng)存在“未經(jīng)你許可”時銷毀了我們的activity的可能時臀防,則onSaveInstanceState()會被系統(tǒng)調(diào)用眠菇,這是系統(tǒng)的責(zé)任边败,因?yàn)樗仨氁峁┮粋€機(jī)會讓你保存你的數(shù)據(jù)(當(dāng)然你不保存那就隨便你了)。如果調(diào)用捎废,調(diào)用將發(fā)生在onPause()或onStop()方法之前笑窜。(雖然測試時發(fā)現(xiàn)多數(shù)在onPause()前)

3. onRestoreInstanceState()什么時候調(diào)用?

  onRestoreInstanceState()被調(diào)用的前提是,activity A“確實(shí)”被系統(tǒng)銷毀了登疗,而如果僅僅是停留在有這種可能性的情況下排截,則該方法不會被調(diào)用,例如辐益,當(dāng)正在顯示activity A的時候断傲,用戶按下HOME鍵回到主界面,然后用戶緊接著又返回到activity A智政,這種情況下activity A一般不會因?yàn)閮?nèi)存的原因被系統(tǒng)銷毀认罩,故activity A的onRestoreInstanceState方法不會被執(zhí)行 此也說明上二者,大多數(shù)情況下不成對被使用续捂。

  onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調(diào)用垦垂。

4. onSaveInstanceState()方法的默認(rèn)實(shí)

  如果我們沒有覆寫onSaveInstanceState()方法, 此方法的默認(rèn)實(shí)現(xiàn)會自動保存activity中的某些狀態(tài)數(shù)據(jù), 比如activity中各種UI控件的狀態(tài).。android應(yīng)用框架中定義的幾乎所有UI控件都恰當(dāng)?shù)膶?shí)現(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)實(shí)現(xiàn):super.onSaveInstanceState(outState)乔外。

5. 是否需要重寫onSaveInstanceState()方法

  既然該方法的默認(rèn)實(shí)現(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ù)庫或文件中)聂渊。說到這里差购,還要說一點(diǎn)的就是在onPause()中不適合用來保存比較費(fèi)時的數(shù)據(jù),所以這點(diǎn)要理解汉嗽。

  由于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è)定, 鍵盤彈出等彰居。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撰筷,隨后出現(xiàn)的幾起案子陈惰,更是在濱河造成了極大的恐慌,老刑警劉巖毕籽,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抬闯,死亡現(xiàn)場離奇詭異井辆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)溶握,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門杯缺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人睡榆,你說我怎么就攤上這事萍肆。” “怎么了肉微?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵匾鸥,是天一觀的道長蜡塌。 經(jīng)常有香客問我碉纳,道長,這世上最難降的妖魔是什么馏艾? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任劳曹,我火速辦了婚禮,結(jié)果婚禮上琅摩,老公的妹妹穿的比我還像新娘铁孵。我一直安慰自己,他們只是感情好房资,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布蜕劝。 她就那樣靜靜地躺著,像睡著了一般轰异。 火紅的嫁衣襯著肌膚如雪岖沛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天搭独,我揣著相機(jī)與錄音婴削,去河邊找鬼。 笑死牙肝,一個胖子當(dāng)著我的面吹牛唉俗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播配椭,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼虫溜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了股缸?” 一聲冷哼從身側(cè)響起吼渡,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乓序,沒想到半個月后寺酪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坎背,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年寄雀,在試婚紗的時候發(fā)現(xiàn)自己被綠了得滤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盒犹,死狀恐怖懂更,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情急膀,我是刑警寧澤沮协,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站卓嫂,受9級特大地震影響慷暂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晨雳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一行瑞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧餐禁,春花似錦血久、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至末盔,卻和暖如春筑舅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庄岖。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工豁翎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隅忿。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓心剥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親背桐。 傳聞我的和親對象是個殘疾皇子优烧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355