寫(xiě)給Android App開(kāi)發(fā)人員看的Android底層知識(shí)(3)

(七)App啟動(dòng)流程第2篇

書(shū)接上文,App啟動(dòng)一共有七個(gè)階段,上篇文章篇幅所限吻育,我們只看了第一階段,接下來(lái)講剩余的六個(gè)階段淤井,仍然是拿斗魚(yú)App舉例子布疼。

簡(jiǎn)單回顧一下第一階段的流程,就是Launcher向AMS發(fā)送一個(gè)跨進(jìn)程通信币狠,通過(guò)AMN/AMP游两,告訴AMS,我要啟動(dòng)斗魚(yú)App漩绵。

畫(huà)一個(gè)圖贱案,描述一下啟動(dòng)App所經(jīng)歷的7個(gè)階段:

第2階段 AMS處理Launcher傳過(guò)來(lái)的信息

這個(gè)階段主要是Binder的Server端在做事情。因?yàn)槲覀兪菦](méi)有機(jī)會(huì)修改Binder的Server端邏輯的止吐,所以這個(gè)階段看起來(lái)非潮ψ伲枯燥,我盡量說(shuō)的簡(jiǎn)單些碍扔。

1. 首先Binder瘩燥,也就是AMN/AMP,和AMS通信不同,肯定每次是做不同的事情颤芬,就比如說(shuō)這次Launcher要啟動(dòng)斗魚(yú)App,那么會(huì)發(fā)送類型為START_ACTIVITY——TRANSACTION的請(qǐng)求給AMS套鹅,同時(shí)會(huì)告訴AMS要啟動(dòng)哪個(gè)Activity站蝠。
?2. AMS說(shuō),好卓鹿,我知道了菱魔,然后它會(huì)干一件很有趣的事情,就是檢查斗魚(yú)App中的Manifest文件吟孙,是否存在要啟動(dòng)的Activity澜倦。如果不存在聚蝶,就拋出Activity not found的錯(cuò)誤,各位做App的同學(xué)對(duì)這個(gè)異常應(yīng)該再熟悉不過(guò)了藻治,經(jīng)常寫(xiě)了個(gè)Activity而忘記在Manifest中聲明了碘勉,就報(bào)這個(gè)錯(cuò),就是因?yàn)锳MS在這里做檢查桩卵。不管是新啟動(dòng)一個(gè)App的首頁(yè)验靡,還是在App內(nèi)部跳轉(zhuǎn)到另一個(gè)Activity,都會(huì)做這個(gè)檢查雏节。
?3. 但是Launcher還活著啊胜嗓,所以接下來(lái)AMS會(huì)通知Launcher,哥們兒沒(méi)你什么事了钩乍,你"停薪留職"吧辞州。那么AMS是通過(guò)什么途徑告訴Launcher的呢?

前面講過(guò)寥粹,Binder的雙方進(jìn)行通信是平等的变过,誰(shuí)發(fā)消息,誰(shuí)就是Client涝涤,接收的一方就是Server媚狰。Client這邊會(huì)調(diào)用Server的代理對(duì)象。

對(duì)于從Launcher發(fā)來(lái)的消息妄痪,通過(guò)AMS的代理對(duì)象AMP哈雏,發(fā)送給AMS。

那么當(dāng)AMS想給Launcher發(fā)消息衫生,又該怎么辦呢裳瘪?前面不是把Launcher以及它所在的進(jìn)程給傳過(guò)來(lái)了嗎?它在AMS這邊保存為一個(gè)ActivityRecord對(duì)象罪针,這個(gè)對(duì)象里面有一個(gè)ApplicationThreadProxy彭羹,單單從名字看就出賣了它,這就是一個(gè)Binder代理對(duì)象泪酱。它的Binder真身派殷,也就是ApplicationThread。

站在AIDL的角度墓阀,來(lái)畫(huà)這張圖毡惜,是這樣的:

所以結(jié)論是,AMS通過(guò)ApplicationThreadProxy發(fā)送消息斯撮,而App端則是通過(guò)ApplicationThread來(lái)接收這個(gè)消息经伙。

第3階段 Launcher去休眠,然后通知AMS勿锅,我真的已經(jīng)"停薪留職"了帕膜,沒(méi)有吃空餉

ApplicationThread(簡(jiǎn)稱APT)枣氧,它和ApplicationThreadProxy(簡(jiǎn)稱ATP)的關(guān)系,我們?cè)诘谌A段已經(jīng)介紹過(guò)了垮刹。

APT接收到來(lái)自AMS的消息后达吞,就調(diào)用ActivityThread的sendMessage方法,向Launcher的主線程消息隊(duì)列發(fā)送一個(gè)PAUSE_ACTIVITY消息荒典。

前面說(shuō)過(guò)酪劫,ActivityThread就是主線程(UI線程)

看到下面的代碼是不是很親切?

發(fā)送消息是通過(guò)一個(gè)名為H的Handler類的完成的种蝶,這個(gè)H類的名字真特么有個(gè)性契耿,想記不住都難瞒大。

做App的同學(xué)都知道螃征,繼承自Handler類的子類,就要實(shí)現(xiàn)handleMessage方法透敌,這里是一個(gè)switch…case語(yǔ)句盯滚,處理各種各樣的消息,PAUSE_ACTIVITY消息只是其中一種酗电,由此也能預(yù)見(jiàn)到魄藕,AMS給Activity發(fā)送的所有消息,以及給其它三大組件發(fā)送的所有消息撵术,都從H這里經(jīng)過(guò)背率,為什么要強(qiáng)調(diào)這一點(diǎn)呢,既然四大組件都走這條路嫩与,那么這里就可以做點(diǎn)手腳寝姿,從而做插件化技術(shù),這個(gè)我們以后介紹插件化技術(shù)的時(shí)候會(huì)講到划滋。

H對(duì)于PAUSE_ACTIVITY消息的處理饵筑,如上面的代碼,是調(diào)用ActivityThread的handlePauseActivity方法处坪。這個(gè)方法干兩件事:

  • ActivityThread里面有一個(gè)mActivities集合根资,保存當(dāng)前App也就是Launcher中所有打開(kāi)的Activity,把它找出來(lái)同窘,讓它休眠玄帕。
  • 通過(guò)AMP通知AMS,我真的休眠了想邦。

你可能會(huì)找不到H和APT這兩個(gè)類文件裤纹,那是因?yàn)樗鼈兌际茿ctivityThread的內(nèi)嵌類。

至此案狠,Launcher的工作完成了服傍。你可以看到在這個(gè)過(guò)程中钱雷,各個(gè)類都起到了什么作用。蕓蕓眾生吹零,粉墨登場(chǎng):

  • APT
  • ActivityThread
  • H

第4階段 AMS啟動(dòng)新的進(jìn)程

接下來(lái)又輪到AMS做事了罩抗,你們會(huì)發(fā)現(xiàn)我不太喜歡講解AMS的流程,甚至都不畫(huà)UML圖灿椅,因?yàn)檫@部分邏輯和App開(kāi)發(fā)人員關(guān)系不是很大套蒂,我盡量說(shuō)的簡(jiǎn)單一些,把流程說(shuō)清楚就好茫蛹。

AMS接下來(lái)要啟動(dòng)斗魚(yú)App的首頁(yè)操刀,因?yàn)槎肤~(yú)App不在后臺(tái)進(jìn)程中,所以要啟動(dòng)一個(gè)新的進(jìn)程婴洼。這里調(diào)用的是Process.start方法骨坑,并且指定了ActivityThread的main函數(shù)為入口函數(shù)。

第5階段 新的進(jìn)程啟動(dòng)柬采,以ActivityThread的main函數(shù)作為入口

啟動(dòng)新進(jìn)程欢唾,其實(shí)就是啟動(dòng)一個(gè)新的App。

在啟動(dòng)新進(jìn)程的時(shí)候粉捻,為這個(gè)進(jìn)程創(chuàng)建ActivityThread對(duì)象礁遣,這就是我們耳熟能詳?shù)闹骶€程(UI線程)。

創(chuàng)建好UI線程后肩刃,立刻進(jìn)入ActivityThread的main函數(shù)祟霍,接下來(lái)要做2件具有重大意義的事情:

1)創(chuàng)建一個(gè)主線程Looper,也就是MainLooper盈包》心牛看見(jiàn)沒(méi),MainLooper就是在這里創(chuàng)建的续语。

2)創(chuàng)建Application垂谢。記住,Application是在這里生成的疮茄。

- - - - - - - - - - - - - -華麗的分割線 開(kāi)始- - - - - - - - - - - - - - -

App開(kāi)發(fā)人員對(duì)Application非常熟悉滥朱,因?yàn)槲覀兛梢栽谄渲袑?xiě)代碼,進(jìn)行一些全局的控制力试,所以我們通常認(rèn)為Application是掌控全局的徙邻,其實(shí)Application的地位在App中并沒(méi)有那么重要,它就是一個(gè)Context上下文畸裳,僅此而已缰犁。

App中的靈魂是ActivityThread,也就是主線程,只是這個(gè)類對(duì)于App開(kāi)發(fā)人員是訪問(wèn)不到的——使用反射倒是可以修改這個(gè)類的一些行為帅容。

- - - - - - - - - - - - - - -華麗的分割線 結(jié)束- - - - - - - - - - - - - - -

創(chuàng)建新App的最后颇象,就是告訴AMS,我啟動(dòng)好了并徘,同時(shí)把自己的ActivityThread對(duì)象發(fā)送給AMS遣钳,從此以后,AMS的電話簿中就多了這個(gè)新的App的登記信息麦乞,AMS以后向這個(gè)App發(fā)送消息蕴茴,就通過(guò)這個(gè)ActivityThread對(duì)象。

第6階段 AMS告訴新App啟動(dòng)哪個(gè)Activity

AMS把傳入的ActivityThread對(duì)象姐直,轉(zhuǎn)為一個(gè)ApplicationThread對(duì)象倦淀,用于以后和這個(gè)App跨進(jìn)程通信。還記得APT和ATP的關(guān)系嗎声畏?這就又回到第2階段的那張關(guān)系圖了撞叽。

還記得第1階段,Launcher發(fā)送給AMS要啟動(dòng)斗魚(yú)App的哪個(gè)Activity嗎砰识?這個(gè)信息被AMS存下來(lái)了能扒。

那么在第6階段佣渴,AMS從過(guò)去的記錄中翻出來(lái)要啟動(dòng)哪個(gè)Activity辫狼,然后通過(guò)ATP告訴App。

第7階段 啟動(dòng)斗魚(yú)首頁(yè)Activity

畢其功于一役辛润,盡在第7階段膨处。這是最后一步。

App砂竖,這個(gè)Binder的另一端真椿,通過(guò)APT接收到AMS的消息,仍然是在H的handleMessage方法的switch語(yǔ)句中處理乎澄,只不過(guò)突硝,這次消息的類型是LAUNCH_ACTIVITY:

ActivityClientRecord是什么?這是AMS傳遞過(guò)來(lái)的要啟動(dòng)的Activity置济。

還是這里解恰,我們仔細(xì)看那個(gè)getPackageInfoNoCheck方法,這個(gè)方法會(huì)提取Apk中的所有資源浙于,然后設(shè)置給r的packageInfo屬性护盈。這個(gè)屬性的類型很有名,叫做LoadedApk羞酗。各位記住這里腐宋,這個(gè)地方可以干壞事,也是插件化技術(shù)滲入的一個(gè)點(diǎn)。

在H的這個(gè)分支中胸竞,又反過(guò)來(lái)回調(diào)ActivityThread的handleLaunchActivity方法欺嗤,你要是覺(jué)得很繞那就對(duì)了。其實(shí)我一直覺(jué)得卫枝,ActivityThread和H合并成一個(gè)類也沒(méi)問(wèn)題剂府。

重新看一下這個(gè)過(guò)程,每次都是APT執(zhí)行ActivityThread的sendMessage方法剃盾,在這個(gè)方法中腺占,把消息拼裝一下,然后扔個(gè)H的swicth語(yǔ)句去分析痒谴,來(lái)決定要執(zhí)行ActivityThread的那個(gè)方法衰伯。每次都是這樣,習(xí)慣就好了积蔚。

handleLaunchActivity方法都做哪些事呢意鲸?

1)通過(guò)Instrumentation的newActivity方法,創(chuàng)建出來(lái)要啟動(dòng)的Activity實(shí)例尽爆。

2)為這個(gè)Activity創(chuàng)建一個(gè)上下文Context對(duì)象怎顾,并與Activity進(jìn)行關(guān)聯(lián)。

3)通過(guò)Instrumentation的callActivityOnCreate方法漱贱,執(zhí)行Activity的onCreate方法槐雾,從而啟動(dòng)Activity》ǎ看到這里是不是很熟悉很親切募强?

至此,App啟動(dòng)完畢崇摄。這個(gè)流程是經(jīng)過(guò)了很多次握手擎值, App和ASM,頻繁的向?qū)Ψ桨l(fā)送消息逐抑,而發(fā)送消息的機(jī)制鸠儿,是建立在Binder的基礎(chǔ)之上的。

下一篇文章厕氨,我們講Context家族进每。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腐巢,隨后出現(xiàn)的幾起案子品追,更是在濱河造成了極大的恐慌,老刑警劉巖冯丙,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肉瓦,死亡現(xiàn)場(chǎng)離奇詭異遭京,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泞莉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門哪雕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鲫趁,你說(shuō)我怎么就攤上這事斯嚎。” “怎么了挨厚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵堡僻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我疫剃,道長(zhǎng)钉疫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任巢价,我火速辦了婚禮牲阁,結(jié)果婚禮上醇蝴,老公的妹妹穿的比我還像新娘吼过。我一直安慰自己,他們只是感情好其做,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布碉克。 她就那樣靜靜地躺著凌唬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棉胀。 梳的紋絲不亂的頭發(fā)上法瑟,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音唁奢,去河邊找鬼。 笑死窝剖,一個(gè)胖子當(dāng)著我的面吹牛麻掸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赐纱,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脊奋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了疙描?” 一聲冷哼從身側(cè)響起诚隙,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎起胰,沒(méi)想到半個(gè)月后久又,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年地消,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炉峰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脉执,死狀恐怖疼阔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情半夷,我是刑警寧澤婆廊,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站巫橄,受9級(jí)特大地震影響否彩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗦随,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一列荔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枚尼,春花似錦贴浙、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至盯质,卻和暖如春袁串,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呼巷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工囱修, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人王悍。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓破镰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親压储。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲜漩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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