謹(jǐn)以文章記錄學(xué)習(xí)歷程,如有錯(cuò)誤還請(qǐng)指明蛋辈。
Activity生命周期
首先放上Google Develop Guides中的Activity完整的生命周期示意圖:
回調(diào)初步解讀
onCreate()
:創(chuàng)建活動(dòng)時(shí)調(diào)用。onStart()
:當(dāng)活動(dòng)進(jìn)入可見狀態(tài)時(shí)調(diào)用,使得活動(dòng)可見但不可與用戶交互坠七。onResume()
:活動(dòng)進(jìn)入前臺(tái)時(shí)調(diào)用水醋,可與用戶交互。onPause()
:活動(dòng)不持有用戶焦點(diǎn)但依然可見時(shí)調(diào)用彪置≈糇伲活動(dòng)仍可見,但停止與用戶交互拳魁,比如彈窗惶桐,鎖屏等onStop()
:活動(dòng)不可見時(shí)調(diào)用onDestroy()
:活動(dòng)退出,被銷毀時(shí)調(diào)用onRestart()
:活動(dòng)由不可見重新返回前臺(tái)時(shí)調(diào)用潘懊。依次調(diào)用onRestart()
->onStart()
->onResume()
回調(diào)方法中進(jìn)行的操作
onCreate()
:在這個(gè)方法中姚糊,執(zhí)行基本的應(yīng)用程序啟動(dòng)邏輯,這種邏輯應(yīng)該只在活動(dòng)的整個(gè)生命周期中發(fā)生一次卦尊。如將數(shù)據(jù)綁定到ListView
叛拷,聲明范圍變量等。同時(shí)該方法接收一個(gè)savedInstanceState
參數(shù)岂却,是用來(lái)恢復(fù)之前保存過(guò)狀態(tài)的Bundle
對(duì)象忿薇。后面我們會(huì)介紹。onStart()
:該方法中初始化維護(hù)UI的組件躏哩,如注冊(cè)一個(gè)監(jiān)聽UI變化的廣播署浩。onResume()
:在這個(gè)方法中,應(yīng)該初始化在onPause()
中釋放的組件扫尺,如初始化camera
筋栋,同時(shí)執(zhí)行活動(dòng)每次進(jìn)入前臺(tái)時(shí)候都需要的初始化操作,如開始動(dòng)畫與初始化哪些只有在獲取用戶焦點(diǎn)時(shí)才需要得到組件正驻,如上下文菜單弊攘。onPause()
:釋放系統(tǒng)資源,例如廣播接收器姑曙、處理傳感器(如GPS
)或任何可能影響電池壽命的資源襟交。onStop()
:釋放幾乎所有不需要的資源,如上述onStart()
中創(chuàng)建的廣播伤靠,同時(shí)在此方法中執(zhí)行耗時(shí)的釋放資源的操作捣域,如保存數(shù)據(jù),網(wǎng)絡(luò)調(diào)用宴合,數(shù)據(jù)庫(kù)事務(wù)等焕梅。同時(shí)很重要的一點(diǎn),需要在此方法中釋放可能導(dǎo)致內(nèi)存泄漏的資源卦洽,因?yàn)橄到y(tǒng)因?yàn)閮?nèi)存緊張而殺死活動(dòng)進(jìn)程時(shí)贞言,不會(huì)調(diào)用最后的onDestroy()
方法。onDestroy()
:釋放在onCreate()
中初始化的活動(dòng)所能使用的全局資源阀蒂。
在任何一個(gè)生命周期回調(diào)方法中調(diào)用
finish()
方法時(shí)蜗字,系統(tǒng)會(huì)直接調(diào)用onDestroy()
方法打肝,而跳過(guò)這之前的所有回調(diào)過(guò)程。
-
onRestart()
:由于onStart()
的存在挪捕,這個(gè)方法好像沒(méi)什么使用場(chǎng)景。
為什么在
onStop()
中釋放耗時(shí)資源而不是在onPause()
中争便?
原因:在兩個(gè)Activity A级零,B中,當(dāng)從A中startActivity()
或startActivityForResult()
啟動(dòng)B時(shí)滞乙,分別以如下的順序調(diào)用生命周期的回調(diào)方法:
- Activity A的
onPause()
- Activity B的
onCreate()
奏纪,onStart()
,onResume()
依次執(zhí)行斩启,此時(shí)Activity B進(jìn)入前臺(tái)并獲得用戶焦點(diǎn)- 如果Activity A不再顯示在屏幕上序调,則調(diào)用其
onStop()
方法。A的
onStop()
方法和B的onCreate()
等一系列方法并非順序執(zhí)行,而是有重疊。因此當(dāng)onPause()
方法中進(jìn)行耗時(shí)操作時(shí)酣难,會(huì)嚴(yán)重影響活動(dòng)之間的跳轉(zhuǎn)速度孽糖。
不同場(chǎng)景下回調(diào)方法的調(diào)用順序
啟動(dòng)Activity
onCreate()
(創(chuàng)建)--->onStart()
(可見,不可交互) --->onResume()
(前臺(tái)钧汹,可交互)currentActivity被otherActivity覆蓋一部分,或鎖屏
onPause()
(失去用戶焦點(diǎn),但仍可見)currentActivity由上述部分不可見狀態(tài)回到前臺(tái)或解鎖屏幕
onResume()
(前臺(tái)墩朦,持有用戶焦點(diǎn))currentActivity轉(zhuǎn)到otherActivity界面,或按Home退回主界面翻擒,自身進(jìn)入后臺(tái)
onPause()
(失去用戶焦點(diǎn)氓涣,但仍可見)--->onStop()
(不可見)由上述后臺(tái)狀態(tài)再次打開該活動(dòng)
onRestart()
(過(guò)渡狀態(tài),不清楚到底有什么用陋气。劳吠。。) --->onStart()
(可見恩伺,不可交互) --->onResume()
(前臺(tái)赴背,持有用戶焦點(diǎn))currentActivity部分可見或后臺(tái)不可見時(shí),系統(tǒng)內(nèi)存不足時(shí)
殺死當(dāng)前Activity晶渠,此時(shí)生命周期不會(huì)發(fā)生回調(diào)上述被殺死的活動(dòng)再次啟動(dòng)
onCreate()
(重新創(chuàng)建) --->onStart()
(可見凰荚,不可交互) --->onResume()
(前臺(tái),持有用戶焦點(diǎn))用戶退出currentActivity
onPause()
(失去用戶焦點(diǎn)褒脯,但仍可見) --->onStop()
(不可見) --->onDestroy()
多窗口下便瑟,ActivityA獲得焦點(diǎn)時(shí),點(diǎn)擊ActivityB
對(duì)于ActivityA:onPause()
(失去用戶焦點(diǎn)番川,但仍可見)
對(duì)于ActivityB:onResume()
(前臺(tái)到涂,持有用戶焦點(diǎn))
Fragment的生命周期
同樣脊框,還是先放上Google Develop Guides中的Fragment完整的生命周期示意圖:
回調(diào)解析
Activity中同名方法不在贅述
onAttach()
Fragment和Activity建立關(guān)聯(lián)時(shí)調(diào)用(獲得activity的傳遞的值,如二者依靠回調(diào)通信時(shí)践啄,獲得activity的引用(將其轉(zhuǎn)型為callback回調(diào)接口))onCreateView()
為Fragment創(chuàng)建視圖(加載布局)時(shí)調(diào)用(給當(dāng)前的fragment繪制UI布局浇雹,可以使用線程更新UI)onActivityCreated()
當(dāng)Activity中的onCreate()
方法執(zhí)行完后調(diào)用(表示activity執(zhí)行oncreate()
方法完成了的時(shí)候會(huì)調(diào)用此方法)onDestroyView()
Fragment中的布局被移除時(shí)調(diào)用onDetach()
Fragment和Activity解除關(guān)聯(lián)的時(shí)候調(diào)用
不同場(chǎng)景下回調(diào)方法的調(diào)用順序
創(chuàng)建一個(gè)fragment的時(shí)候
創(chuàng)建過(guò)程:onAttach()
--->onCreate()
--->onCreateView()
--->onActivityCreated()
顯示到前臺(tái):onStart()
--->onResume()
fragment進(jìn)入后臺(tái)
onPause()
--->onStop()
fragment被銷毀
onPause()
--->onStop()
--->onDestroyView()
--->onDestroy()
--->onDetach()
鎖屏
onPause()
--->onStop()
解鎖
onStart()
--->onResume()
打開其他fragment(原始fragment被替換,或完全不可見)
onPause()
--->onStop()
--->onDestroyView()
上述條件下back回原始fragment
onCreateView()
--->onActivityCreated()
->onStart()
--->onResume()
Home回到桌面
onPause()
--->onStop()
上述回到原始fragment
onStart()
--->onResume()
退出應(yīng)用
onPause()
--->onStop()
--->onDestroyView()
--->onDestroy()
--->onDetach()
二者生命周期的聯(lián)系
老規(guī)矩屿讽,還是放上Google Develop Guides中的對(duì)比圖
由于Android內(nèi)部機(jī)制(原理尚不知昭灵,未深入源碼做研究),fragment總是依附于activity而存在伐谈,不過(guò)需要注意的是activity的生命周期由系統(tǒng)控制烂完,而fragment則是由宿主activity控制,因此在activity進(jìn)入到某一狀態(tài)如created诵棵,系統(tǒng)會(huì)調(diào)用activity的
onCreate()
抠蚣,此時(shí)宿主activity會(huì)調(diào)用fragment的onAttach()
...onActivityCreated()
一系列方法,使得fragment快速跟上宿主履澳,與宿主activity保持一致狀態(tài)嘶窄。
關(guān)于Activity狀態(tài)保存與恢復(fù)
在上述生命周期中,我們有時(shí)會(huì)需要保存activity的狀態(tài)奇昙,比如我們正在某一文本框EditText中輸入文本時(shí)护侮,此時(shí)退出應(yīng)用之后再次打開時(shí),我們會(huì)發(fā)現(xiàn)文本框的內(nèi)容消失了储耐。消失了羊初。。消失了什湘。长赞。。
這種情況下闽撤,用戶體驗(yàn)顯然不會(huì)好得哆。因此Google引入了保存UI狀態(tài)這一概念。
保存狀態(tài)
復(fù)寫onSaveInstanceState()
哟旗,傳入一個(gè)帶有狀態(tài)信息的Bundle
對(duì)象贩据,代碼如下:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
保存狀態(tài)的時(shí)機(jī)
Activity容易被銷毀的時(shí)候調(diào)用:
- 按下
Home
鍵:Activity進(jìn)入了后臺(tái) - 鎖屏:Activity進(jìn)入后臺(tái)
- 啟動(dòng)其他Activity:Activity進(jìn)入后臺(tái)
- 橫豎屏切換:銷毀并重建Activity實(shí)例
上述場(chǎng)景下,多數(shù)為當(dāng)系統(tǒng)內(nèi)存不足時(shí)闸餐,可能銷毀后臺(tái)低優(yōu)先級(jí)的Activity饱亮。
注意事項(xiàng)
在用戶主動(dòng)銷毀Activity時(shí)不會(huì)保存狀態(tài):
back
鍵- 調(diào)用
finish()
方法方法調(diào)用時(shí)機(jī):
- Android P之前:介于
onStop()
之前,但不確定在onPause()
之前還是之后舍沙。- Android P中:在
onStop()
后調(diào)用設(shè)有id的組件會(huì)自動(dòng)保存組件的狀態(tài)
恢復(fù)狀態(tài)
我們有兩種方式恢復(fù)狀態(tài):
- 在
onCreate()
方法恢復(fù)
需要注意的是近上,在嘗試讀取該對(duì)象時(shí),需要判斷其是否為空拂铡,空時(shí)則會(huì)創(chuàng)建該活動(dòng)的新實(shí)例壹无,而非恢復(fù)之前被銷毀活動(dòng)實(shí)例:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
// ...
}
- 重寫
onRestoreInstanceState()
方法恢復(fù)
只有在有待恢復(fù)的狀態(tài)時(shí)葱绒,系統(tǒng)才調(diào)用onRestoreInstanceState()
,所以不需要檢查savedInstanceState
是否為空:
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
調(diào)用時(shí)機(jī)
- 銷毀了之后重建的時(shí)候調(diào)用, 如果內(nèi)存充足, 系統(tǒng)沒(méi)有銷毀這個(gè) Activity, 就不需要調(diào)用
- 橫豎屏切換時(shí)調(diào)用
總結(jié)
- 本文盡可能詳細(xì)的對(duì)Activity和Fragment的生命周期斗锭,以及Activity的狀態(tài)保存與恢復(fù)作出了解析
- 筆者水平有限地淀,如有錯(cuò)漏,歡迎指正拒迅。
- 接下來(lái)我也會(huì)將所學(xué)的知識(shí)分享出來(lái)骚秦,有興趣可以繼續(xù)關(guān)注whd_Alive的Android開發(fā)筆記
歡迎關(guān)注whd_Alive的簡(jiǎn)書
- 不定期分享Android開發(fā)相關(guān)的技術(shù)干貨,期待與你的交流璧微,共勉。