深入理解Activity生命周期、啟動模式及IntentFilter

Activity作為Android四大組件中最常用的組件,對其進(jìn)行深入的學(xué)習(xí)是一個初級Android開發(fā)人員成長路上的必修課梁沧。
本篇文章主要針對Activity的生命周期異常狀態(tài)恢復(fù)坛梁、啟動模式以及Intent隱式啟動做相應(yīng)的深入學(xué)習(xí)奏黑,挖掘Activity的各項(xiàng)進(jìn)階知識。

1.Activity的生命周期

先上一張官方的Activity生命周期圖

Activity生命周期

接下來我們對Activity生命周期中的各狀態(tài)進(jìn)行逐一分析:
(1)onCreate:該方法只在Activity第一次被創(chuàng)建的時候調(diào)用孩擂。我們常常在其中進(jìn)行一些初始化的操作狼渊,如setContentView、綁定事件、初始化各類數(shù)據(jù)等狈邑。
(2)onStart:該方法表示Activity正在啟動城须。一般發(fā)生在Activity由不可見轉(zhuǎn)變?yōu)榭梢姇r被調(diào)用。(此時的Activity已經(jīng)可見了米苹,但還沒出現(xiàn)在前臺糕伐,無法進(jìn)行交互)
(3)onResume:該方法表示Activity不僅已經(jīng)可見,而且此刻位于前臺蘸嘶,可以與用戶進(jìn)行交互良瞧。此時該Activity一定位于當(dāng)前返回棧的棧頂,且處于運(yùn)行狀態(tài)训唱。
(4)onPause:該方法表示Activity正在停止褥蚯,一般情況下onStop方法會緊接著被調(diào)用。通常我們會在這個方法中去做一些儲存數(shù)據(jù)况增、釋放資源的操作赞庶。此時該Activity將不再位于前臺。注意的是澳骤,該方法中切不可執(zhí)行耗時操作尘执,否則會影響到新Activity的顯示。
(5)onStop:該方法在活動完全不可見時被調(diào)用宴凉,可以在該方法內(nèi)執(zhí)行一些稍微重量級的回收工作誊锭,同樣不可太耗時。
(6)onDestroy:該方法表示Activity即將被銷毀弥锄,這是Activity生命周期中的最后一步丧靡,應(yīng)該在該方法內(nèi)執(zhí)行最終的回收工作和資源釋放。
(7)onRestart:該方法在Activity由停止?fàn)顟B(tài)轉(zhuǎn)為運(yùn)行狀態(tài)的過程中被調(diào)用籽暇,一般發(fā)生在返回到上一個Activity這種情況下温治。

上述7個生命周期中的回調(diào)方法中,除了OnRestart方法戒悠,其他方法都是兩兩相對的熬荆,我們可以從下面幾種角度對它們進(jìn)行加深理解:
Activity創(chuàng)建和銷毀的角度來看,分別對應(yīng)著OnCreate和OnDestroy绸狐;
Activity是否可見的角度來看卤恳,分別對應(yīng)著OnStart和OnStop;
Activity是否位于前臺的角度來看寒矿,分別對應(yīng)著OnResume和OnPause突琳。

下面列舉幾種情況下Activity的執(zhí)行流程:
①Activity啟動:onCreate->onStart->onResume
②打開新Activity或切換到桌面:onPause->onStop(特殊情況,當(dāng)新Activity采用透明主題時符相,當(dāng)前Activity不會回調(diào)onStop)
③回到原Activity:onRestart->onStart->onResume
④按back鍵回退:onPause->onStop->onDestroy

特別說明:

當(dāng)啟動一個新Activity時拆融,一定是先執(zhí)行當(dāng)前Activity的onPause方法后,才會啟動新的Activity,最后執(zhí)行當(dāng)前Activity的onStop方法镜豹。(所以onPause方法中一定不能執(zhí)行耗時操作)

2.Activity異常狀態(tài)下的生命周期

當(dāng)資源相關(guān)的系統(tǒng)配置發(fā)生改變或是系統(tǒng)內(nèi)存不足時傲须,Activity可能會被殺死。由于Activity是被異常銷毀掉的趟脂,所以用戶的一些臨時數(shù)據(jù)需要進(jìn)行保存泰讽,以使該Activity重新創(chuàng)建時能復(fù)現(xiàn)銷毀時的內(nèi)容,如EditText中的內(nèi)容等散怖。
由系統(tǒng)內(nèi)存不足所涉及到的進(jìn)程優(yōu)先級的問題菇绵,參考Android的進(jìn)程優(yōu)先級
當(dāng)系統(tǒng)配置發(fā)生改變后镇眷,Activity會被銷毀咬最,其onPause、onStop欠动、onDestroy均會被調(diào)用永乌,同時由于Activity是在異常情況下被終止的,所以系統(tǒng)會調(diào)用onSaveInstanceState方法來保存當(dāng)前Activity的狀態(tài)具伍。該方法的調(diào)用時機(jī)在onStop之前翅雏,但和onPause沒有絕對的時序關(guān)系。
當(dāng)Activity被重新創(chuàng)建之后人芽,系統(tǒng)會回調(diào)onRestoreInstanceState方法望几,并把Activity銷毀時在onSaveInstanceState方法中所保存的Bundle作為參數(shù)傳遞到onCreate和onRestoreInstanceState方法中。從時序上來說萤厅,onRestoreInstanceState調(diào)用時機(jī)在onStart之后橄抹。
onRestoreInstanceState和onCreate雖然都能獲得異常時傳入Bundle參數(shù),但是二者還是有一定的區(qū)別:onRestoreInstanceState方法一旦被調(diào)用惕味,其Bundle參數(shù)一定是有值的楼誓;而onCreate方法在正常啟動的時候,其Bundle參數(shù)為null名挥,所以必須進(jìn)行額外的判斷才行疟羹。官方推薦使用onRestoreInstanceState方法進(jìn)行數(shù)據(jù)恢復(fù)。

多次試驗(yàn)后的總結(jié)下禀倔,onSaveInstanceState(Bundle outState)會在以下情況被調(diào)用:
1榄融、當(dāng)用戶按下HOME鍵時。
2蹋艺、從最近應(yīng)用中選擇運(yùn)行其他的程序時剃袍。
3、按下電源按鍵(關(guān)閉屏幕顯示)時捎谨。
4、從當(dāng)前activity啟動一個新的activity時。
5涛救、屏幕方向切換時(無論豎屏切橫屏還是橫屏切豎屏都會調(diào)用)畏邢。

在前4種情況下,當(dāng)前activity的生命周期為:
onPause -> onSaveInstanceState -> onStop -> onRestart -> onStart -> onResume
當(dāng)該activity重新位于前臺時检吆,并不會執(zhí)行onRestoreInstanceState方法舒萎。

第五種情況下,當(dāng)前activity的生命周期為:
onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume

當(dāng)然蹭沛,當(dāng)系統(tǒng)配置發(fā)生變化時臂寝,Activity也能不被重建。通過給Activity指定configChanges屬性可以實(shí)現(xiàn)這一目標(biāo)摊灭,如不想讓Activity在屏幕旋轉(zhuǎn)時重建咆贬,就可以給configChanges屬性添加orientation這個值。
android:configChanges="orientation"
通常我們用的只有l(wèi)ocal(系統(tǒng)語言)帚呼、orientation(屏幕方向)和keyboardHidden(調(diào)出鍵盤)這三個選項(xiàng)掏缎。

3.Activity的啟動模式

系統(tǒng)會將啟動的Activity放入ActivityTask中,該任務(wù)棧遵循后進(jìn)先出的規(guī)則煤杀。當(dāng)然眷蜈,Android中還能通過指定lauchmode的方式來個性化activity在棧中的啟動模式。

Activity有四種啟動模式standard沈自、singleTop酌儒、singleTask和singleInstance。

standard:activity的默認(rèn)啟動模式枯途。每次啟動一個Activity的時候都會重新創(chuàng)建一個新的實(shí)例壓入棧頂忌怎,不管當(dāng)前棧中是否已存在該Activity。
singleTop棧頂復(fù)用模式柔袁。如果當(dāng)前任務(wù)棧的棧頂是該Activity呆躲,那么此Activity不會被重新創(chuàng)建,同時會調(diào)用棧頂Activity的onNewIntent方法捶索,通過此方法獲取當(dāng)前的請求信息插掂。此時該Activity的onCreate、onStart不會被系統(tǒng)調(diào)用腥例,僅執(zhí)行onPause -> onNewIntent -> onResume辅甥;如果新Activity的實(shí)例在任務(wù)棧中已存在但并未位于棧頂,那么新Activity則依舊會重新創(chuàng)建燎竖。
singleTask棧內(nèi)復(fù)用模式璃弄。這是一種單實(shí)例模式,該模式下构回,只要當(dāng)前任務(wù)棧內(nèi)存在即將要啟動的Activity(不管在棧內(nèi)何處)夏块,那么當(dāng)前棧中該Activity上面的所有Activity都將出棧疏咐,并且該Activity將位于棧頂。和singleTop一樣脐供,singleTask也會調(diào)用該Activity的onNewIntent方法浑塞。(注意:singleTask模式下可以指定該Activity啟動所需要的任務(wù)棧,若指定任務(wù)棧不存在政己,則會新建對應(yīng)的任務(wù)棧后再把該Activity新建的實(shí)例放進(jìn)去)酌壕。
singleInstance單實(shí)例模式。指定為singleInstance的Activity會啟用一個新的任務(wù)棧來管理自身歇由。只要該Activity未銷毀卵牍,由于棧內(nèi)復(fù)用的特性,后續(xù)的請求不會再創(chuàng)建新的任務(wù)棧沦泌,會一直復(fù)用處于該任務(wù)棧內(nèi)的Activity糊昙。

特殊情況:TaskAffinity

上面提到在singleTask模式下,Activity需要選擇自己所指定的任務(wù)棧赦肃,那么這個指定的任務(wù)棧又是在哪實(shí)現(xiàn)的呢溅蛉?
答案就在TaskAffinity這個屬性上。該參數(shù)能標(biāo)識Activity所需任務(wù)棧的名字他宛,默認(rèn)情況下所有Acitivity的任務(wù)棧都為應(yīng)用的包名船侧。TaskAffinity屬性的值為字符串,且中間必須包含包名分隔符“.”厅各。TaskAffinity屬性主要和singleTask模式或者allowTaskReparenting屬性配對使用镜撩,在其他情況下沒有意義。
當(dāng)TaskAffinity和singleTask模式配對使用時队塘,待啟動的Activity會運(yùn)行在TaskAffinity指定的任務(wù)棧中袁梗。
當(dāng)TaskAffinity和allowTaskReparenting配對使用時,情況較為復(fù)雜憔古。例如有兩個應(yīng)用A和B遮怜,A啟動了B中的Activity并且該Activity設(shè)置的allowTaskReparenting屬性為true,那么當(dāng)用戶按home建回到桌面后再點(diǎn)擊應(yīng)用B圖標(biāo)鸿市,則不是啟動了B的Launch Activity锯梁,而是重新顯示的之前被A所啟動的那個Activity

除了通過launchmode來指定Activity的啟動模式焰情,還能通過Intent來動態(tài)指定Activity的啟動模式陌凳。其中,Intent動態(tài)指定的優(yōu)先級高于在xml中的靜態(tài)注冊方式内舟。
動態(tài)指定主要是通過往Intent中添加Flag實(shí)現(xiàn)合敦,如
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

以下列舉幾個常見的標(biāo)記位,稍作理解即可验游。
FLAG_ACTIVITY_NEW_TASK:和在xml中指定singleTask模式相同
FLAG_ACTIVITY_SINGLE_TOP:和在xml中指定singleTop模式相同
FLAG_ACTIVITY_CLEAR_TOP:啟動該Activity時充岛,與其同一任務(wù)棧中所有位于它上面的Activity都要出棧保檐。如果被啟動的Activity采用standard模式,那么連同它之上的Activity都要出棧裸准,系統(tǒng)再創(chuàng)建新的Activity實(shí)例放入棧頂展东。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有此標(biāo)記的Activity不會出現(xiàn)在歷史Activity列表中赔硫。等同于在xml中指定Activity屬性android:excludeFromRencents="true"炒俱。

4.IntentFilter

IntentFilter主要作用于Intent的隱式調(diào)用中。IntentFilter為Intent的隱式調(diào)用設(shè)置了過濾規(guī)則爪膊,如果不匹配將無法成功啟動目標(biāo)Activity权悟。IntentFilter中過濾的信息有actioncategory推盛、data峦阁。

一個Activity中可以有多個intent-filter,一個Intent只要能匹配任何一組intent-filter就可以成功啟動對應(yīng)的Activity耘成。

action:action的匹配要求是Intent中的action存在且必須和過濾規(guī)則中的其中一個action相同榔昔,這里的相同指的是Intent中的action必須能夠和過濾規(guī)則中的action的字符串的值完全一樣。action區(qū)分大小寫瘪菌。

categoryIntent中如果含有category撒会,那么所有出現(xiàn)的category都必須和過濾規(guī)則中的其中一個category相同。(為了使Activity能接受到隱式調(diào)用师妙,必須在intent-filter中指定"android.intent.category.DEFAULT"這個category诵肛,以免在Intent未指定category時添加的默認(rèn)值無法匹配)

data:data和action的匹配原則類似。由于data的結(jié)構(gòu)過于復(fù)雜且平時較少涉及到默穴,故此處不展開學(xué)習(xí)怔檩。

在action和category中,有一類action和category比較特別:

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

它們的共同作用標(biāo)明了這是一個入口Activity蓄诽,二者缺一不可薛训。


參考文獻(xiàn):

《第一行代碼——Android(第2版)》
《Android開發(fā)藝術(shù)探索》
《深入理解Android內(nèi)核設(shè)計(jì)思想》



若您覺得本文章對您有用,請您為我點(diǎn)上一顆小心心以表支持仑氛。感謝乙埃!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市调衰,隨后出現(xiàn)的幾起案子膊爪,更是在濱河造成了極大的恐慌,老刑警劉巖嚎莉,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件米酬,死亡現(xiàn)場離奇詭異,居然都是意外死亡趋箩,警方通過查閱死者的電腦和手機(jī)赃额,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門加派,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跳芳,你說我怎么就攤上這事芍锦。” “怎么了飞盆?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵娄琉,是天一觀的道長。 經(jīng)常有香客問我吓歇,道長孽水,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任城看,我火速辦了婚禮女气,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘测柠。我一直安慰自己炼鞠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布轰胁。 她就那樣靜靜地躺著谒主,像睡著了一般。 火紅的嫁衣襯著肌膚如雪软吐。 梳的紋絲不亂的頭發(fā)上瘩将,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機(jī)與錄音凹耙,去河邊找鬼姿现。 笑死,一個胖子當(dāng)著我的面吹牛肖抱,可吹牛的內(nèi)容都是我干的备典。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼意述,長吁一口氣:“原來是場噩夢啊……” “哼提佣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起荤崇,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拌屏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后术荤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倚喂,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年瓣戚,在試婚紗的時候發(fā)現(xiàn)自己被綠了端圈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焦读。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖舱权,靈堂內(nèi)的尸體忽然破棺而出矗晃,到底是詐尸還是另有隱情,我是刑警寧澤宴倍,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布张症,位于F島的核電站,受9級特大地震影響啊楚,放射性物質(zhì)發(fā)生泄漏吠冤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一恭理、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧郭变,春花似錦颜价、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至未荒,卻和暖如春专挪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背片排。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工寨腔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人率寡。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓迫卢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冶共。 傳聞我的和親對象是個殘疾皇子乾蛤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容