Activity生命周期以及啟動(dòng)模式

一,安卓的七大生命周期

onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy | onRestart

onCreate:Activity正在被創(chuàng)建
onStart:已經(jīng)可見(jiàn)但是還不在前臺(tái)庭瑰,無(wú)法交互
onResume:已經(jīng)可以開(kāi)始交互了
onPause:Activity正在停止星持,onStop會(huì)被緊接著調(diào)用。不應(yīng)該在這個(gè)階段做耗時(shí)操作弹灭,只有這個(gè)方法執(zhí)行完督暂,新的Activity的onResume才能被執(zhí)行
onStop:Activity即將停止,可以做一些重量級(jí)回收工作鲤屡,也不能太耗時(shí)
onDestroy:Activity即將被銷毀损痰,可以做一些資源釋放和回收工作
onRestart:表示Activity重新啟動(dòng),一般由不可見(jiàn)變?yōu)榭梢?jiàn)時(shí)被調(diào)用

注意事項(xiàng):

  1. 用戶打開(kāi)的新的Activity是透明主題酒来,原來(lái)的Activity的onStop不會(huì)被調(diào)用
  2. 回到上一個(gè)Activity卢未,該Activity生命周期回調(diào):onRestart -> onStart -> onResume
  3. 當(dāng)用戶按下返回鍵,當(dāng)前Activity生命周期回調(diào):onPause -> onStop -> onDestroy
  4. Activity A啟動(dòng)Activity B堰汉,生命周期:A onPause -> B onCreate -> B onStart -> B onResume -> A onStop
  5. Activity被系統(tǒng)回收后重新啟動(dòng)生命周期從頭走一遍
  6. onStart和onStop是關(guān)于Activity可見(jiàn)不可見(jiàn)而調(diào)用的辽社,onResume和onPause是關(guān)于Activity是否位于前臺(tái)來(lái)調(diào)用的,因此這四個(gè)方法都會(huì)隨著用戶熄滅屏幕翘鸭、亮起屏幕而頻繁調(diào)用

二滴铅,安卓異常情況下的生命周期

  1. 當(dāng)系統(tǒng)配置發(fā)生改變后,Activity會(huì)被銷毀就乓,其onPause汉匙、onStop、onDestroy均會(huì)被調(diào)用生蚁,同時(shí)由于Activity是在異常情況下終止的噩翠,系統(tǒng)會(huì)調(diào)用onSaveInstanceState來(lái)保存當(dāng)前Activity的狀態(tài)。這個(gè)方法的調(diào)用時(shí)機(jī)是在onStop之前邦投,它和onPause沒(méi)有既定的時(shí)序關(guān)系伤锚,它既可能在onPause之前調(diào)用,也可能在onPause之后調(diào)用志衣。需要強(qiáng)調(diào)的一點(diǎn)是屯援,這個(gè)方法只會(huì)出現(xiàn)在Activity被異常終止的情況下猛们,正常情況下系統(tǒng)不會(huì)回調(diào)這個(gè)方法∧螅總結(jié)如下:
    (onPause/onSaveInstanceState)->(onPause/onSaveInstanceState)-> onStop -> onDestroy
  2. 異常情況終止下弯淘,onSaveInstanceState保存的數(shù)據(jù)可以通過(guò)onCreate和onRestoreInstanceState的形參Bundle傳入。因此在onCreate中對(duì)Bundle進(jìn)行判空可以判斷是否是異常終止然后重建的徘铝,而onRestoreInstanceState在異常情況下重建必然會(huì)被調(diào)用耳胎,所以傳入的Bundle一定不為空。官方推薦在onRestoreInstanceState方法中進(jìn)行數(shù)據(jù)恢復(fù)惕它。onRestoreInstanceState方法調(diào)用時(shí)機(jī)在onStart之后怕午。
  3. 注意:onSaveInstanceState和onRestoreInstanceState方法只有在Activity被銷毀并且有機(jī)會(huì)重新顯示的情況下才會(huì)被調(diào)用。例如屏幕旋轉(zhuǎn)淹魄,Activity被銷毀但是又要立即展示出來(lái)郁惜;資源不足,低優(yōu)先級(jí)被回收甲锡,但是用戶可能還會(huì)回到那個(gè)界面兆蕉,還有機(jī)會(huì)展示。所以正常的銷毀是不會(huì)調(diào)用這兩個(gè)方法的缤沦!
  4. 關(guān)于Activity的優(yōu)先級(jí):
    4.1 前臺(tái)Activity虎韵,優(yōu)先級(jí)最高
    4.2 可見(jiàn)但非前臺(tái)Activity,例如這個(gè)Activity彈出一個(gè)Dialog缸废,這時(shí)候Activity不能交互包蓝,但是可見(jiàn),優(yōu)先級(jí)其次
    4.3 后臺(tái)Activity企量,已經(jīng)位于后臺(tái)被暫停测萎,例如執(zhí)行了onStop,優(yōu)先級(jí)最低
  5. 對(duì)于系統(tǒng)配置變更后Activity其實(shí)是有辦法不進(jìn)行重建的届巩,在清單文件中對(duì)應(yīng)的Activity加上android:configChanges="orientation"硅瞧,但是當(dāng)minSdkVersion或者targetSdkVersion大于13時(shí),為了防止重建還得加上screenSize恕汇,也就是這樣了:“android:configChanges="orientation|screenSize”

三腕唧,安卓啟動(dòng)模式

standard:默認(rèn)啟動(dòng)模式,每次啟動(dòng)就在啟動(dòng)它的那個(gè)Activity所在的任務(wù)棧的棧頂添加一個(gè)Activity實(shí)例瘾英。所以我們?cè)谑褂肁pplicationContext啟動(dòng)Activity的時(shí)候就會(huì)報(bào)錯(cuò)枣接,因?yàn)榉茿ctivity類的Context沒(méi)有任務(wù)棧。解決辦法就是添加一個(gè)FLAG_ACTIVITY_NEW_TASKFLAG
singleTop:棧頂復(fù)用模式方咆。每次啟動(dòng)前看看棧頂是否有當(dāng)前需要啟動(dòng)的Activity的實(shí)例月腋,如果有則不會(huì)創(chuàng)建新的實(shí)例蟀架,而且Activity的onCreate和onStart都不會(huì)被調(diào)用瓣赂,會(huì)在onResume回調(diào)之前回調(diào)一個(gè)onNewIntent的方法榆骚,并且可以從這個(gè)方法的形參中可以取出請(qǐng)求信息。
singleTask:棧內(nèi)復(fù)用模式煌集。只要即將啟動(dòng)的Activity實(shí)例在任何一個(gè)棧內(nèi)存在妓肢,那么該棧會(huì)置于前臺(tái),并且該Activity實(shí)例上所有的Activity會(huì)被移出棧苫纤,同樣會(huì)在onResume之前調(diào)用onNewIntent碉钠。流程如下(假如需要啟動(dòng)Activity A):

singleTask啟動(dòng)流程

singleTask:單實(shí)例模式。就相當(dāng)于加強(qiáng)的singleTask卷拘,但是這個(gè)模式下喊废,這種Activity會(huì)獨(dú)占一個(gè)任務(wù)棧。

注意事項(xiàng)
  1. 什么是Activity所需的任務(wù)棧栗弟?這個(gè)跟taskAffinity屬性有關(guān)污筷,默認(rèn)情況Activity所需的任務(wù)棧名字和應(yīng)用包名一致。我們可以給每個(gè)Activity單獨(dú)制定這個(gè)參數(shù)乍赫,而且屬性值不能與包名相同瓣蛀,不然就相當(dāng)于沒(méi)有指定。這個(gè)屬性一般和singleTask啟動(dòng)模式或者allowTaskReparenting一起使用雷厂。
  2. 如何理解taskAffinity為什么需要和singleTask啟動(dòng)模式或者allowTaskReparenting成對(duì)使用惋增?因?yàn)橹付藅askAffinity就相當(dāng)于指定了任務(wù)棧名字,所以只有啟動(dòng)的Activity需要一個(gè)新的任務(wù)棧(啟動(dòng)模式為singleTask或者singleInstance這種就是需要一個(gè)新的任務(wù)棧)才會(huì)起作用改鲫。但是其實(shí)對(duì)于singleInstance诈皿,taskAffinity是不起作用的,加入taskAffinity指定同樣的名稱钩杰,多次啟動(dòng)不同的Activity纫塌,這些Activity的啟動(dòng)模式是singleInstance的話,他們還是會(huì)在不同的任務(wù)棧讲弄。因?yàn)閟ingleInstance會(huì)使一個(gè)Activity獨(dú)占一個(gè)任務(wù)棧措左。同樣,allowTaskReparenting這個(gè)屬性的作用是指定出現(xiàn)符合taskAffinity屬性值的任務(wù)棧是否將Activity從啟動(dòng)它的任務(wù)棧中移至符合的任務(wù)棧中避除,true代表移動(dòng)呕乎,false代表不移動(dòng)。例子:A啟動(dòng)B應(yīng)用中的C這個(gè)Activity:


    image.png

四篮条,如何給Activity指定啟動(dòng)模式

一是通過(guò)AndroidMenifest種Activity標(biāo)簽下添加launchMode屬性為Activity指定啟動(dòng)模式
二是在實(shí)例化Intent的時(shí)候給它設(shè)置Flag馍驯,例如:

Intent intent = new Intent(this, SecondActivity.class);
intent.addFlag(Intent.FLAG_ACTIVITY_NEW_TASK);

這兩種方法,第二種優(yōu)先級(jí)更高群井。

Flags

FLAG_ACTIVITY_NEW_TASK:為Activity指定“singleTask”啟動(dòng)模式状飞。
FLAG_ACTIVITY_SINGLE_TOP:為Activity指定“singleTop”啟動(dòng)模式。
FLAG_ACTIVITY_CLEAR_TOP:添加此標(biāo)記,啟動(dòng)目標(biāo)Activity時(shí)在同一個(gè)任務(wù)棧中所有位于這個(gè)Activity實(shí)例之上的Activity都要出棧诬辈。這個(gè)一般需要配合FLAG_ACTIVITY_NEW_TASK一起使用酵使,在這個(gè)情況下如果目標(biāo)Activity已經(jīng)有實(shí)例,那么會(huì)調(diào)用它的onNewIntent焙糟。如果目標(biāo)Activity的啟動(dòng)方式是standard口渔,那么它連同它之上的Activity都會(huì)出棧,然后系統(tǒng)會(huì)創(chuàng)建一個(gè)它的新的實(shí)例放入棧頂穿撮。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有這個(gè)標(biāo)記的Activity不會(huì)出現(xiàn)在歷史Activity的列表中缺脉,等同于在清單文件中Activity標(biāo)簽下指定android:excludeFromRecents="true"

五悦穿,IntentFilter的匹配規(guī)則

啟動(dòng)Activity的方式有兩種攻礼,分別是顯式調(diào)用和隱式調(diào)用。
注意:顯式調(diào)用需要明確地指定被啟動(dòng)對(duì)象的組件信息栗柒,包括包名和類名秘蛔,而隱式調(diào)用則不需要明確指定組件信息。原則上一個(gè)Intent不應(yīng)該既是顯式調(diào)用又是隱式調(diào)用傍衡,如果二者共存的話以顯式調(diào)用為主深员。
隱式調(diào)用需要Intent能夠匹配目標(biāo)組件的IntentFilter中所設(shè)置的過(guò)濾信息,如果不匹配將無(wú)法啟動(dòng)目標(biāo)Activity蛙埂。IntentFilter中的過(guò)濾信息有action倦畅、category、data绣的,他們分別可以有多個(gè)叠赐,分別構(gòu)成不同類別的匹配,只有三者同時(shí)匹配上了屡江,才算匹配上了對(duì)應(yīng)的Activity芭概!另外,一個(gè)Activity可以有多個(gè)IntentFilter惩嘉,但是一個(gè)Intent只要能匹配上其中一組就可以了罢洲。

  1. action的匹配規(guī)則:Intent中的action必須能夠和過(guò)濾規(guī)則中的action的字符串值完全一樣(區(qū)分大小寫),過(guò)濾規(guī)則中action可以有多個(gè)文黎,只要Intent能匹配上一個(gè)就算匹配成功惹苗,但是Intent沒(méi)有action就算匹配失敗。
  2. category的匹配規(guī)則:Intent中只要有category耸峭,那么Intent中所有的category都必須在過(guò)濾規(guī)則中有就算匹配成功桩蓉。如果Intent沒(méi)有category則也算匹配成功。注意:系統(tǒng)在調(diào)用startActivity或者startActivityForResult的時(shí)候會(huì)默認(rèn)為Intent加上“android.intent.category.DEFAULT”這個(gè)category劳闹,所以如果過(guò)濾規(guī)則中添加了“android.intent.category.DEFAULT”這個(gè)category院究,我們的Intent不添加category也是可以匹配的
  3. data匹配規(guī)則:
    3.1 data的數(shù)據(jù)分為以下幾種:
    android:scheme="string":URI的模式洽瞬,比如http、file业汰、content等片任,如果URI中沒(méi)有指定scheme,那么整個(gè)URI的其他參數(shù)無(wú)效蔬胯,這也意味著URI是無(wú)效的。
    android:host="string":URI的主機(jī)名位他,比如www.baidu.com氛濒,如果host未指定,那么整個(gè)URI中的其他參數(shù)無(wú)效鹅髓,這也意味著URI是無(wú)效的舞竿。
    android:port="string":URI中的端口號(hào),比如80窿冯,僅當(dāng)URI中指定了scheme和host參數(shù)的時(shí)候port參數(shù)才是有意義的骗奖。
    android:path="string":表示完整的路徑信息。
    android:pathPattern="string":表示路徑的完整信息醒串,但是可以使用正則表達(dá)式進(jìn)行匹配执桌。
    android:pathPrefix="string":表示路徑的前綴信息
    android:mimeType="string”:指定媒體類型,例如:“image/*”
    主要其實(shí)就是兩大部分芜赌,一是mimeType仰挣,二是uri。uri的組成:<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]缠沈。例如:http://www.baidu.com:80/search/info
    3.2 data匹配規(guī)則與action類似膘壶,它要求Intent中必須含有data數(shù)據(jù),并且data數(shù)據(jù)能夠完全匹配Intent-filter中的某一個(gè)data洲愤。
    特殊情況說(shuō)明:例如過(guò)濾規(guī)則中指明了mimeType="image/*"颓芭,雖然沒(méi)有指定uri,但是uri是有默認(rèn)值的柬赐,默認(rèn)值的schema為content和file亡问。所以也就是說(shuō)Intent需要額為加上uri,schema必須為content或者file才能匹配肛宋。另外玛界,Intent如果需要同時(shí)指定data和mimeType的話必須調(diào)用setDataAndType方法,不能單獨(dú)調(diào)用setData之后又調(diào)用setType方法悼吱,這會(huì)使得這兩個(gè)屬性相互覆蓋慎框。
過(guò)濾規(guī)則(隱式調(diào)用)總結(jié)
  1. 隱式調(diào)用下,如果無(wú)法匹配對(duì)應(yīng)的Activity會(huì)報(bào)錯(cuò)后添。同理笨枯,隱式調(diào)用BroadcastReceiver和Service也會(huì)出現(xiàn)類似的錯(cuò)誤。為了避免這種錯(cuò)誤,可以采用PackageManager的resolveActivity方法或者Intent的resolveActivity方法馅精,如果它們找不到匹配的Activity就會(huì)返回null严嗜。
  2. 另外,PackageManager還提供了queryIntentActivities方法洲敢,這個(gè)方法和resolveActivity方法不同的是:它不是返回最佳匹配的Activity信息而是返回所有成功匹配的Activity信息漫玄。
  3. queryIntentActivities方法對(duì)比resolveActivity方法,這兩個(gè)方法原型如下:
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,int flags);
public abstract ResolveInfo resolveActivity(Intent intent,int flags);

上面方法中第二個(gè)參數(shù)要使用MATCH_DEFAULT_ONLY這個(gè)標(biāo)志压彭,這個(gè)標(biāo)志的含義是僅僅匹配在過(guò)濾規(guī)則中聲明了<category android:name="android.intent.category.DEFAULT"/>這個(gè)category的Activity睦优。使用這個(gè)標(biāo)記位的意義在于,只要上述兩個(gè)方法不返回null壮不,那么startActivity一定可以成功汗盘。如果不用這個(gè)標(biāo)記位,就可以把intent-filter中category不含DEFAULT的那些Activity給匹配出來(lái)询一,從而導(dǎo)致startActivity可能失敗隐孽。因?yàn)椴缓蠨EFAULT這個(gè)category的Activity是無(wú)法接收隱式Intent的。

  1. 在action和category中健蕊,有一類action和category比較重要菱阵,它們是:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

這二者共同作用是用來(lái)標(biāo)明這是一個(gè)入口Activity并且會(huì)出現(xiàn)在系統(tǒng)的應(yīng)用列表中,少了任何一個(gè)都沒(méi)有實(shí)際意義缩功,也無(wú)法出現(xiàn)在系統(tǒng)的應(yīng)用列表中送粱,也就是二者缺一不可。另外掂之,針對(duì)Service和BroadcastReceiver抗俄,PackageManager同樣提供了類似的方法去獲取成功匹配的組件信息。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末世舰,一起剝皮案震驚了整個(gè)濱河市动雹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跟压,老刑警劉巖胰蝠,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異震蒋,居然都是意外死亡茸塞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門查剖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钾虐,“玉大人,你說(shuō)我怎么就攤上這事笋庄⌒ǎ” “怎么了倔监?”我有些...
    開(kāi)封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)菌仁。 經(jīng)常有香客問(wèn)我浩习,道長(zhǎng),這世上最難降的妖魔是什么济丘? 我笑而不...
    開(kāi)封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任谱秽,我火速辦了婚禮,結(jié)果婚禮上摹迷,老公的妹妹穿的比我還像新娘疟赊。我一直安慰自己,他們只是感情好泪掀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著颂碘,像睡著了一般异赫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上头岔,一...
    開(kāi)封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天塔拳,我揣著相機(jī)與錄音,去河邊找鬼峡竣。 笑死靠抑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的适掰。 我是一名探鬼主播颂碧,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼类浪!你這毒婦竟也來(lái)了载城?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤费就,失蹤者是張志新(化名)和其女友劉穎诉瓦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體力细,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睬澡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了眠蚂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片煞聪。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖逝慧,靈堂內(nèi)的尸體忽然破棺而出米绕,到底是詐尸還是另有隱情瑟捣,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布栅干,位于F島的核電站迈套,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碱鳞。R本人自食惡果不足惜桑李,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窿给。 院中可真熱鬧贵白,春花似錦、人聲如沸崩泡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)角撞。三九已至呛伴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谒所,已是汗流浹背热康。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劣领,地道東北人姐军。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像尖淘,于是被迫代替她去往敵國(guó)和親奕锌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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