Activity相關(guān)知識(shí)總結(jié)

異常情況下的生命周期

情況一:資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被銷毀并重建

比較典型的就是橫豎屏的切換伙判、字體大小的變化或者分辨率的變化荠藤,默認(rèn)情況下系統(tǒng)會(huì)將Activity銷毀并重建。此時(shí)系統(tǒng)會(huì)調(diào)用onSaveInstanceState方法保存Activity的狀態(tài)(判斷的標(biāo)準(zhǔn)是系統(tǒng)認(rèn)為Activity被銷毀后按灶,會(huì)立刻被重建),onSaveInstanceState的調(diào)用發(fā)生在onStop之前,與onPause的調(diào)用沒有固定的先后順序惹悄。Activity被重建時(shí),系統(tǒng)會(huì)調(diào)用onRestoreInstanceState方法肩钠,它的調(diào)用發(fā)生在onStart之后泣港,與onResume沒有固定的先后順序。在Activity被重建時(shí)价匠,可以選擇在onRestoreInstanceState或onCreate方法中讀取bundle數(shù)據(jù)恢復(fù)之前的Activity狀態(tài)当纱,唯一的區(qū)別是,如果onRestoreInstanceState被調(diào)用那參數(shù)中的bundle對(duì)象一定不會(huì)為null踩窖。

在異常情況下坡氯,系統(tǒng)銷毀Activity時(shí),會(huì)默認(rèn)保存一些視圖狀態(tài),比如ListView的滾動(dòng)位置箫柳,EditText輸入的內(nèi)容和聚焦?fàn)顟B(tài)手形。這是因?yàn)閂iew也有onSaveInstanceState和onRestoreInstanceState方法。當(dāng)Activity被銷毀時(shí)悯恍,首先觸發(fā)其onSaveInstanceState方法库糠,然后Activity會(huì)委托(或者叫分發(fā)任務(wù))它的window對(duì)象保存相關(guān)數(shù)據(jù),觸發(fā)其onSaveInstanceState方法涮毫,繼而window對(duì)象會(huì)委托它所包含的View層級(jí)曼玩,逐層觸發(fā)各個(gè)view的onSaveInstanceState方法,這樣就就保存狀態(tài)的任務(wù)窒百,分發(fā)到了Activity的視圖所包含的所有View對(duì)象黍判。

情況二 內(nèi)存不足導(dǎo)致系統(tǒng)需要銷毀低優(yōu)先級(jí)的Activity

Activity根據(jù)優(yōu)先級(jí)的高低,可以分為三種:

(1)前臺(tái)Activity——處于onResume狀態(tài)篙梢,正在與用戶交互

(2)可見Activity——處于onPause狀態(tài)顷帖,用戶可見,但是不能交互渤滞。比如從Activity觸發(fā)彈出對(duì)話框贬墩,此時(shí)Activity即為可見狀態(tài),但是不可交互妄呕。

(3)后臺(tái)Activity——處于onStop的狀態(tài)陶舞,Activity不可見,已經(jīng)暫停绪励。

系統(tǒng)內(nèi)存資源不足時(shí)肿孵,會(huì)按照優(yōu)先級(jí)去殺掉目標(biāo)Activity所在的進(jìn)程,并在后續(xù)通過onSaveInstanceState和onRestoreInstanceState方法來存儲(chǔ)和恢復(fù)數(shù)據(jù)疏魏。

系統(tǒng)配置項(xiàng)里有很多內(nèi)容停做,如果某個(gè)內(nèi)容項(xiàng)發(fā)生變化時(shí),我們不希望Activity被系統(tǒng)重建大莫,可以給Activity在manifest配置中指定configChanges屬性蛉腌。當(dāng)Activity指定了configChanges屬性后,相應(yīng)的系統(tǒng)配置項(xiàng)發(fā)生變化時(shí)只厘,Activity將不會(huì)被銷毀烙丛,onSaveInstanceState和onRestoreInstanceState方法也不會(huì)被調(diào)用,取而代之的是羔味,系統(tǒng)會(huì)調(diào)用Activity的onConfigurationChanged方法河咽。


Activity啟動(dòng)模式

standard——默認(rèn)的標(biāo)準(zhǔn)模式。關(guān)于standard介评,值得注意的是库北,如果用ApplicationContext.startActivity啟動(dòng)standard模式的Activity爬舰,就會(huì)報(bào)錯(cuò)。原因是非Acitivity類型的context對(duì)象沒有任務(wù)棧(task)寒瓦,而standard模式的Acitivity默認(rèn)是要進(jìn)入啟動(dòng)它的Activity所在的任務(wù)棧情屹。解決的方法就是,啟動(dòng)Activity時(shí)杂腰,給Intent設(shè)置FLAG_ACTIVITY_NEW_TASK標(biāo)識(shí)垃你,這樣實(shí)際上相當(dāng)于將Activity的啟動(dòng)模式變?yōu)閟ingleTask。

singleTop——值得注意的是onNewIntent觸發(fā)時(shí)機(jī)喂很。比如重復(fù)調(diào)用在棧頂?shù)膕ingleTop模式的Activity惜颇,只有三個(gè)生命周期方法會(huì)被觸發(fā),onPause->onNewIntent->onResume少辣。

應(yīng)用場(chǎng)景:網(wǎng)易新聞凌摄。

假設(shè)主界面為 MainActivity,顯示新聞的界面是 DetailActivity漓帅,顯然顯示任何一條新聞都會(huì)使用 DetailActivity锨亏,即把新聞內(nèi)容通過 Intent 傳給 DetailActivity 就可以了。

假設(shè)你正在看新聞1(即在 DetailActivity)忙干,此時(shí)手機(jī)收到服務(wù)器的推送:收到一條通知(新聞2)器予,點(diǎn)擊通知就會(huì)跳轉(zhuǎn)到 DetailActivity 并顯示新聞2,當(dāng)你點(diǎn)擊通知時(shí)捐迫,因?yàn)槟壳皸m數(shù)?Activity 就是 DetailActivity乾翔,因此這里就是使用 SingleTop 的地方,即點(diǎn)擊通知后以 SingleTop 加載模式打開 DetailActivity 并顯示新聞2施戴,因此新聞1的 DetailActivity 就被覆蓋掉了反浓。

此后你點(diǎn)擊返回鍵會(huì)回到主界面。

singleTask——模式為singleTask的Activity啟動(dòng)時(shí)暇韧,并不一定會(huì)新建一個(gè)Task勾习。具體取決于taskAffinity的參數(shù)浓瞪。比如懈玻,只是給Activity設(shè)置了singleTask。而沒有指定taskAffinity乾颁,則該Activity會(huì)歸入到默認(rèn)的Task(名稱為包名)涂乌。當(dāng)singleTask模式的Activity啟動(dòng)時(shí),如果taskAffinity指定的Task已經(jīng)存在英岭,就不會(huì)新建Task湾盒。

應(yīng)用場(chǎng)景:微信的主界面(一般應(yīng)用主界面都會(huì)以 SingleTask 啟動(dòng))。

你打開微信主界面(在棧的最底部)后诅妹,進(jìn)入朋友圈(在棧的頂部)罚勾,此時(shí)你點(diǎn)擊 Home 鍵回桌面毅人,并打開網(wǎng)易新聞。

假設(shè)你想將網(wǎng)易新聞的一條新聞分享給微信好友尖殃,那么就按照 分享->微信->好友A->分享給他->留在微信丈莺。接著會(huì)跳轉(zhuǎn)微信的主界面,即不是你原本所在的朋友圈送丰,并且微信的棧只剩下一個(gè)元素:主界面的 Activity缔俄。這里就使用了 SingleTask(即以 SingleTask 加載模式打開微信主界面)。

singleInstance——Activity和所在的Task只會(huì)被創(chuàng)建一次器躏,具有全局唯一性俐载,之后每次啟動(dòng)都會(huì)復(fù)用這個(gè)Activity實(shí)例。而singleInstance模式的Activity啟動(dòng)其他Activity登失,等同于自動(dòng)標(biāo)記為FLAG_ACTIVITY_NEW_TASK遏佣。

應(yīng)用場(chǎng)景:鬧鈴的響鈴界面。

系統(tǒng)電話撥號(hào)界面揽浙,無論從任何其他應(yīng)用跳轉(zhuǎn)到撥號(hào)界面贼急,你會(huì)發(fā)現(xiàn),之前輸入的電話號(hào)碼一直都在捏萍,即表示此Acitivity始終是同一實(shí)例被復(fù)用太抓。


FLAGS

FLAG_ACTIVITY_NEW_TASK——等價(jià)于將Activity的啟動(dòng)模式設(shè)置為singleTask。

FLAG_ACTIVITY_SINGLE_TOP——等價(jià)于將Activity的啟動(dòng)模式設(shè)置為singleTop令杈。

FLAG_ACTIVITY_CLEAR_TOP——值得注意的是走敌,如果被啟動(dòng)的Activity是standard模式,那么它本來的實(shí)例和在它之上的Activity都會(huì)被出棧逗噩,然后系統(tǒng)會(huì)重新創(chuàng)建該Activity的實(shí)例

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS——具備這個(gè)標(biāo)識(shí)的Activity不會(huì)出現(xiàn)在歷史Activity的列表中掉丽,等同于在manifest中為Activity設(shè)置android:excludeFromRecents="true"。(但是這個(gè)標(biāo)識(shí)在不同版本的Android系統(tǒng)中异雁,不一定起作用捶障,已經(jīng)有人在stackoverflow發(fā)問過,google的開發(fā)人員有過回應(yīng)纲刀,需要修復(fù)這個(gè)問題项炼。)


task和back stack

task是一組Activity的集合,back stack是task的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)示绊。task是可以跨應(yīng)用锭部,跨進(jìn)程的。


taskAffinity和allowTaskReparenting

taskAffinity可以理解為一個(gè)task的名稱面褐。主要和singleTask啟動(dòng)模式或者allowTaskReparenting配對(duì)使用拌禾。

一個(gè)task的affinity取決于棧中最底部的Activity(root Activity)的taskAffinity屬性。如果沒有指定展哭,默認(rèn)是和包名相同湃窍。

taskAffinity屬性相同的Activity在同一個(gè)task闻蛀。同時(shí)也意味著,我們可以根據(jù)taskAffinity屬性將同一個(gè)應(yīng)用Activity分組到不同的task您市,更重要的是循榆,也可以將不同應(yīng)用的Activity分組到同一個(gè)task,只要taskAffinity屬性值相同墨坚。如果將Activity的taskAffinity屬性設(shè)置為空字符串秧饮,表示這個(gè)Activity不屬于任何task。

taskAffinity屬性和allowTaskReparenting屬性配對(duì)使用泽篮,會(huì)產(chǎn)生特殊的效果盗尸。當(dāng)應(yīng)用A啟動(dòng)了應(yīng)用B的Activity,此時(shí)如果taskAffinity沒有特指帽撑,那么Activity會(huì)在應(yīng)用A的任務(wù)棧中泼各。若allowTaskReparenting屬性設(shè)置為true,則當(dāng)應(yīng)用B啟動(dòng)時(shí)亏拉,Activity將從應(yīng)用A的任務(wù)棧轉(zhuǎn)移到應(yīng)用B的任務(wù)棧扣蜻。


intentFilter的匹配規(guī)則

action的匹配規(guī)則要求Intent中action不能為空,且必須與過濾規(guī)則的其中一個(gè)action匹配及塘,且區(qū)分大小寫莽使。

category,intent中可以設(shè)置多個(gè)category笙僚,對(duì)于每一個(gè)category都必須與過濾規(guī)則的其中一個(gè)category匹配芳肌。intent也可以沒有category,因?yàn)橄到y(tǒng)在隱式啟動(dòng)Activity時(shí)肋层,會(huì)默認(rèn)加上“android.intent.category.DEFAULT”這個(gè)category亿笤。所以我們要在接受隱式調(diào)用的intentFilter中加上“android.intent.category.DEFAULT”這個(gè)category。

data栋猖,和action的匹配規(guī)則相同净薛。data有mimeType和URI兩部分組成。URI由包括scheme蒲拉、host肃拜、port、path等全陨。如果data中沒有指定URI爆班,系統(tǒng)會(huì)默認(rèn)URI為content和file。也就是說辱姨,雖然不打算指定URI,intent中data的URI部分的scheme也必須是content或者file才能匹配戚嗅,這點(diǎn)需要注意雨涛。另外枢舶,要為intent指定完整的data,應(yīng)該調(diào)用setDataAndType替久,不能先調(diào)用setData凉泄,再調(diào)用setType。因?yàn)檫@兩個(gè)方法彼此會(huì)清除對(duì)方的值蚯根。

intentFilter對(duì)Service和boardcastReceiver的匹配規(guī)則也是同樣的道理后众,只是系統(tǒng)建議對(duì)Service的啟動(dòng)盡量用顯示調(diào)用。


判斷一個(gè)隱式intent是否有相匹配的Activity可以啟動(dòng)颅拦,有兩個(gè)方法:

1 PachageManager的resolveActivity或者intent的resolveActivity方法蒂誉,返回的是最佳匹配的Activity,如果找不到匹配的Activity會(huì)返回null距帅。

2 PackageManager的queryIntentActivities方法右锨,返回的是所有匹配的Activity信息。

resolveActivity和queryIntentActivities方法都要傳兩個(gè)參數(shù)碌秸。其中第二個(gè)參數(shù)flags需要注意的是绍移,MATCH_DEFAULT_ONLY,這個(gè)標(biāo)識(shí)的意思是僅僅匹配那些在intent-filter中聲明了“android.intent.category.DEFAULT”這個(gè)category的的Activty讥电。使用這個(gè)標(biāo)識(shí)位的意義是蹂窖,只要resolveActivity方法不返回null,startActivity就一定可以成功恩敌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恼策,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子潮剪,更是在濱河造成了極大的恐慌涣楷,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抗碰,死亡現(xiàn)場(chǎng)離奇詭異狮斗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)弧蝇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門碳褒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人看疗,你說我怎么就攤上這事沙峻。” “怎么了两芳?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵摔寨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我怖辆,道長(zhǎng)是复,這世上最難降的妖魔是什么删顶? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮淑廊,結(jié)果婚禮上逗余,老公的妹妹穿的比我還像新娘。我一直安慰自己季惩,他們只是感情好录粱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著画拾,像睡著了一般啥繁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碾阁,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天输虱,我揣著相機(jī)與錄音,去河邊找鬼脂凶。 笑死宪睹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚕钦。 我是一名探鬼主播亭病,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼嘶居!你這毒婦竟也來了罪帖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤邮屁,失蹤者是張志新(化名)和其女友劉穎整袁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佑吝,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坐昙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芋忿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炸客。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖戈钢,靈堂內(nèi)的尸體忽然破棺而出痹仙,到底是詐尸還是另有隱情,我是刑警寧澤殉了,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布开仰,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抖所。R本人自食惡果不足惜梨州,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一痕囱、第九天 我趴在偏房一處隱蔽的房頂上張望田轧。 院中可真熱鬧,春花似錦鞍恢、人聲如沸傻粘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弦悉。三九已至,卻和暖如春蟆炊,著一層夾襖步出監(jiān)牢的瞬間稽莉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國打工涩搓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留污秆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓昧甘,卻偏偏與公主長(zhǎng)得像良拼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子充边,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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