Application实檀、Activity惶洲、Service和Context之間的構(gòu)建關(guān)系

一、Context與Application膳犹、Activity恬吕、Service的繼承關(guān)系

? ? ? ?在開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)遇到使用context的情況须床,如通過(guò)context得到resource铐料,通過(guò)context實(shí)現(xiàn)layoutInflater等,在代碼環(huán)境中使用context豺旬,可用通過(guò)activity钠惩、application以及service來(lái)實(shí)現(xiàn),那么這是為什么呢族阅?

? ? ? ?因?yàn)槿叨际抢^承自context抽象類的篓跛,如下圖所示:

? ? ? ?可以看到,activity是繼承自ContextThemeWrapper坦刀,而Service和Application繼承自ContextWrapper

? ? ? ?對(duì)于ContextWrapper和ContextThemeWrapper而言愧沟,兩者存在繼承關(guān)系,最終繼承自Context鲤遥,而Context實(shí)際上是一個(gè)抽象類央渣,它的實(shí)現(xiàn)是交給ContextImpl類負(fù)責(zé),所以可以先提一下渴频,app在啟動(dòng)時(shí)芽丹,application、activity和service三者能夠關(guān)聯(lián)到context卜朗,實(shí)際上都是在創(chuàng)建者三個(gè)要素的時(shí)候拔第,同時(shí)實(shí)現(xiàn)了ContextImpl對(duì)象咕村,具體證明放在之后描述。

? ? ? 知道了activity蚊俺、service和application與context的關(guān)系之后懈涛,也就理解了為什么可以把這仨當(dāng)context來(lái)用了,其實(shí)context意義為場(chǎng)景泳猬,而activity批钠、service及application從語(yǔ)義上理解也是場(chǎng)景的概念。

? ? ? 那么還有一個(gè)問(wèn)題得封,activity等著仨是如何實(shí)現(xiàn)各自context的對(duì)應(yīng)關(guān)系呢埋心,需要分析app的啟動(dòng)過(guò)程了。

二 忙上、Context與三者的對(duì)應(yīng)關(guān)系描述

? ? ? ?在app啟動(dòng)時(shí)拷呆,或者啟動(dòng)一個(gè)新的activity及service中,實(shí)際上先由AmS(Activity Manager Service)來(lái)負(fù)責(zé)疫粥,AmS在一個(gè)進(jìn)程中茬斧,啟動(dòng)的Activity或app是由另一個(gè)所在進(jìn)程ActivityThread來(lái)實(shí)現(xiàn),AmS負(fù)責(zé)管理ActivityThread中的相關(guān)具體過(guò)程梗逮,因此需要實(shí)現(xiàn)跨進(jìn)程間的數(shù)據(jù)交互项秉,而AmS和ActivityThread的數(shù)據(jù)交互入口是ActivityThread中的ApplicationThread,ApplicationThread是一個(gè)Binder變量慷彤,可以接受AmS傳遞來(lái)的數(shù)據(jù)娄蔼。

2.1 Application與Context的關(guān)系

? ? ? ?application初啟動(dòng)時(shí),對(duì)于ActivityThread中瞬欧,首先會(huì)執(zhí)行到bindApplication方法贷屎,該方法的聲明如下:

可以在參數(shù)列表中發(fā)現(xiàn)有一個(gè)ApplicationInfo類型的參數(shù)appInfo罢防,該數(shù)據(jù)實(shí)際上是由AmS傳遞過(guò)來(lái)的艘虎,且ApplicationInfo類型實(shí)現(xiàn)了Parcelable接口。

? ? ? ?在調(diào)用了bindApplication方法之后咒吐,通過(guò)傳遞來(lái)的appInfo野建,會(huì)構(gòu)建一個(gè)AppBindData類型的數(shù)據(jù),該數(shù)據(jù)構(gòu)建完成之后恬叹,會(huì)由ActivityThread的內(nèi)部Handler發(fā)送一個(gè)消息:

此時(shí)候生,ActivityThread由于實(shí)現(xiàn)了Handler的handleMessage,所以在收到消息為BIND_APPLICATION時(shí)會(huì)回調(diào)handleBindApplication方法,在該方法中可以找到創(chuàng)建Application的過(guò)程:
可以看到一個(gè)關(guān)鍵方法data.info.makeApplication()

? ? ? ? 這里的data就是之前創(chuàng)建完成的AppBindData類型的绽昼,也是handleBindApplication的傳入?yún)?shù);info是LoadApk類型唯鸭,在老版本中info實(shí)際上就是PackageInfo這個(gè)類,所以LoadApk就是PackageInfo硅确,LoadApk這個(gè)類中有makeApplication方法目溉,在該方法中存在實(shí)現(xiàn)context和application關(guān)聯(lián)的步驟明肮,查看makeApplication方法:

在makeApplication方法中,創(chuàng)建了ContextImpl對(duì)象缭付,并在ActivityThread中柿估,通過(guò)Instrumentation對(duì)象創(chuàng)建了app,然后將app設(shè)置為context的外在體現(xiàn)陷猫,即setOuterContext方法秫舌,該方法如下:
該方法接收一個(gè)context對(duì)象,把其設(shè)置成mOuterContext绣檬,其實(shí)就是代言人的概念了足陨。

? ? ? ?以上就實(shí)現(xiàn)了application的創(chuàng)建過(guò)程中實(shí)現(xiàn)context關(guān)聯(lián)的過(guò)程,再由流程圖的形式描述一下:

2.2 Activity與Context的關(guān)系

? ? ? ? activity與context的關(guān)系也類似與application的流程河咽,啟動(dòng)activity時(shí)钠右,首先也是交由AmS進(jìn)行處理,AmS會(huì)傳遞一個(gè)ActivityInfo類型的數(shù)據(jù)給ActivityThread忘蟹,然后ActivityThread拿到了該數(shù)據(jù)之后執(zhí)行后續(xù)的一系列操作飒房。ActivityInfo也是一個(gè)實(shí)現(xiàn)Parcelable接口的類型。

ScheduleLaunchActivity這個(gè)方法相當(dāng)于在接收到AmS傳遞來(lái)的ActivityInfo之后媚值,執(zhí)行的預(yù)處理工作狠毯,這個(gè)預(yù)處理主要是updateProcessState和構(gòu)建ActivityClientRecord對(duì)象,完成之后sendMessage
看到了Activity是如何明面上創(chuàng)建的了褥芒,接下來(lái)執(zhí)行到performLaunchActivity方法中:
從上面的代碼中就了解了Activity對(duì)象是如何創(chuàng)建的嚼松,以及Context對(duì)象是如何關(guān)聯(lián)到activity的,可以看看createBaseContextForActivity這個(gè)方法的具體實(shí)現(xiàn):
可以看到在該方法中锰扶,同樣通過(guò)ContextImpl的靜態(tài)方法createActivityContext來(lái)創(chuàng)建ContextImpl對(duì)象献酗,然后通過(guò)setOuterContext來(lái)設(shè)置activity為context的外部代言人

? ? ? ?整體流程如下:

2.3 Service與Context的關(guān)系

? ? ? ? 與上述兩種情況類似,啟動(dòng)Service(注意這里是startService而不是bindService)時(shí)坷牛,首先AmS進(jìn)行處理罕偎,包裝出一個(gè)ServiceInfo類型的數(shù)據(jù),ActivityThread接收到數(shù)據(jù)后首先執(zhí)行scheduleCreateService方法:

創(chuàng)建了CreateServiceData之后發(fā)送消息CREATE_SERVICE京闰,然后得到handleMessage的響應(yīng)颜及,進(jìn)入到handleCreateService方法中:

? ? ? ?在該方法中,首先通過(guò)getPackageInfoNoCheck得到了packageInfo對(duì)象蹂楣,根據(jù)該對(duì)象得到ClassLoader后通過(guò)反射構(gòu)建了service俏站,獲取了service對(duì)象之后,利用ContextImpl的靜態(tài)方法得到了context痊土,context設(shè)置了service為其外部代言人肄扎,之后創(chuàng)建了application,將service attach上去,最后啟動(dòng)onCreate方法犯祠。

? ? ? ?有一個(gè)疑問(wèn)萌丈,為什么在創(chuàng)建了service的過(guò)程中需要構(gòu)建application對(duì)象呢?可能是跟后臺(tái)service依舊屬于一個(gè)application雷则,雖然沒(méi)有前臺(tái)界面的展示辆雾,沒(méi)有明顯的application構(gòu)建,但是service需要依賴application月劈,所以針對(duì)無(wú)界面度迂、后臺(tái)service啟動(dòng)的情況下需要?jiǎng)?chuàng)建application為service提供attach支持。

? ? ? ?整體流程如下:

三猜揪、總結(jié)

? ? ? 通過(guò)第二部分的分析惭墓,可以總結(jié)如下:

? ? ? 不論是啟動(dòng)app還是某個(gè)activity,亦或是service而姐,最初都需要提交給AmS腊凶,AmS相當(dāng)于總負(fù)責(zé)人,總負(fù)責(zé)人處理好消息后打包成數(shù)據(jù)(ApplicationInfo拴念、ActivityInfo及ServiceInfo)钧萍,并將數(shù)據(jù)通過(guò)跨進(jìn)程傳遞的方式遞交給ActivityThread進(jìn)行處理,ActivityThread在接收時(shí)對(duì)外首先暴露ApplicationThread這個(gè)Binder接口政鼠,然后獲取到相應(yīng)的數(shù)據(jù)之后執(zhí)行創(chuàng)建application风瘦、activity及service的流程;同時(shí)在創(chuàng)建這仨時(shí)公般,通過(guò)ContextImpl的靜態(tài)方法來(lái)創(chuàng)建ContextImpl對(duì)象万搔,對(duì)象創(chuàng)建完成之后通過(guò)setOuterContext方法指定各類的外部代言人,但是該方法的參數(shù)是Context官帘,而恰好Application瞬雹、Activity及Service都繼承自Context,所有可以有效充當(dāng)contextImpl的外部代言人刽虹,來(lái)調(diào)用contextImpl中的方法酗捌,這就是application、activity及service是context的本質(zhì)状婶,本質(zhì)在于以代言人的身份調(diào)用方法(好像屬于一類設(shè)計(jì)模式?)意敛。

? ? ?多提一句馅巷,contextImpl內(nèi)的核心實(shí)現(xiàn)其實(shí)大部分都在LoadApk方法內(nèi)具體完成的膛虫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市钓猬,隨后出現(xiàn)的幾起案子稍刀,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件账月,死亡現(xiàn)場(chǎng)離奇詭異综膀,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)局齿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門剧劝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人抓歼,你說(shuō)我怎么就攤上這事讥此。” “怎么了谣妻?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵萄喳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蹋半,道長(zhǎng)他巨,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任减江,我火速辦了婚禮染突,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辈灼。我一直安慰自己觉痛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布茵休。 她就那樣靜靜地躺著薪棒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪榕莺。 梳的紋絲不亂的頭發(fā)上俐芯,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音钉鸯,去河邊找鬼吧史。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唠雕,可吹牛的內(nèi)容都是我干的贸营。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岩睁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钞脂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起捕儒,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冰啃,失蹤者是張志新(化名)和其女友劉穎邓夕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阎毅,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焚刚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扇调。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矿咕。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖狼钮,靈堂內(nèi)的尸體忽然破棺而出痴腌,到底是詐尸還是另有隱情,我是刑警寧澤燃领,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布士聪,位于F島的核電站,受9級(jí)特大地震影響猛蔽,放射性物質(zhì)發(fā)生泄漏剥悟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一曼库、第九天 我趴在偏房一處隱蔽的房頂上張望区岗。 院中可真熱鬧,春花似錦毁枯、人聲如沸慈缔。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)藐鹤。三九已至,卻和暖如春赂韵,著一層夾襖步出監(jiān)牢的瞬間娱节,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工祭示, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肄满,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓质涛,卻偏偏與公主長(zhǎng)得像稠歉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汇陆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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