android 9.0 startActivity流程

好記性不如爛筆桿弄慰。所以還是有必要給這些都記下來闹蒜,隔段時(shí)間再看的時(shí)候也不至于一片茫然沪蓬。

順帶提一下目前自己閱讀源碼的三種途徑:1.在線閱讀,類似的網(wǎng)站有androidxref等斑胜;2.使用工具如Source Insight 4.0導(dǎo)入源碼進(jìn)行閱讀控淡;3.使用as加載修改過的android.jar包來進(jìn)行閱讀。這三種更喜歡as的方式止潘,函數(shù)的跳轉(zhuǎn)和變量的顏色區(qū)分的最好掺炭,Source Insight可能用的不熟練,總感覺比as差點(diǎn)事覆山,但是Source Insight好處就是占用內(nèi)存資源少竹伸,而網(wǎng)站更適合查找部分代碼,比如各個(gè)版本代碼的不同部分簇宽。

好了勋篓,開始正題。startActivity在最近的幾個(gè)安卓版本中部分代碼做了改動(dòng)魏割,雖然整體還是一樣的架構(gòu)譬嚣,比如;7.0之前是binder來實(shí)現(xiàn)進(jìn)程間通信的钞它,8.0之后改為aidl去實(shí)現(xiàn)了拜银,雖然本質(zhì)上實(shí)現(xiàn)還是binder,aidl只是又做了一層封裝遭垛;又比如9.0在啟動(dòng)activity上與之前的啟動(dòng)方式相比尼桶,由函數(shù)直接調(diào)用改為類似事物的方式去啟動(dòng)了。但是锯仪,整體的架構(gòu)還是一樣的泵督,ams仍然是那個(gè)最重要的中間者,而啟動(dòng)的最后仍然會(huì)回到activityThread中去處理庶喜。

在activity中調(diào)用startActivity小腊,首先會(huì)調(diào)用Activity類中的startActivity方法,以前的老版本這一步是調(diào)用context的startActivity方法久窟;


此方法會(huì)調(diào)用

此處傳入startActivity方法的第二個(gè)參數(shù)為null秩冈,因此我們直接跟進(jìn)else里面的方法startActivityForResult(intent, -1);


在此方法中我們又看到了熟悉的類Instrumentation,在Instrumentation類中調(diào)用了execStartActivity斥扛,需要注意的是這是個(gè)重載方法入问,我們只找我們參數(shù)對(duì)應(yīng)的方法即可,下面是這個(gè)方法的關(guān)鍵代碼


此處開始進(jìn)程切換稀颁。ActivityManager.getService().startActivity這段代碼其實(shí)是跨進(jìn)程調(diào)用了ActivityManagerService里面的方法startActivity队他,關(guān)于ActivityManagerService這個(gè)服務(wù)(以下簡稱AMS)的作用此處不做講解。下面來看下ActivityManager.getService()這個(gè)方法的具體實(shí)現(xiàn)


可以看到getService方式內(nèi)部調(diào)用了IActivityManagerSingleton.get()峻村,IActivityManagerSingleton其實(shí)是一個(gè)泛型單例類麸折,核心實(shí)現(xiàn)是重寫的create方法,此方法內(nèi)部通過調(diào)用ServiceManager.getService(Context.ACTIVITY_SERVICE)得到一個(gè)java層的binder粘昨,ServiceManager是系統(tǒng)Service服務(wù)的管家垢啼,內(nèi)部維護(hù)了一個(gè)map來存儲(chǔ)各個(gè)Service對(duì)象窜锯,ACTIVITY_SERVICE就是AMS在map的key值。IActivityManager.Stub.asInterface(b)這行代碼就屬于aidl的范疇了芭析,asInterface方法據(jù)說內(nèi)部調(diào)用了native方法通過binder驅(qū)動(dòng)锚扎,然后經(jīng)過映射找到另一個(gè)進(jìn)程的binder,然后層層返回馁启,最后到j(luò)ava層驾孔,這樣我們就拿到了可以和另一個(gè)進(jìn)程進(jìn)行通信的鑰匙。

8.0之前這一部分沒有使用aidl惯疙,而是直接使用binder實(shí)現(xiàn)的翠勉,具體的代碼在ActivityManagerNative這個(gè)類里面。替換為binder之后代碼更為精簡了霉颠,便于閱讀对碌,對(duì)于初學(xué)者也更為友好,不用在ActivityManagerNative和代理類之間繞來繞去的蒿偎,而機(jī)器生成的代碼比人寫的代碼也更為安全朽们。

接下來繼續(xù)startActivity的流程,代碼在系統(tǒng)進(jìn)程AMS的startActivity處開始


此處留意第一個(gè)參數(shù)IApplicationThread caller诉位,后續(xù)有用


第二個(gè)startActivityAsUser方法也是和之前不一樣的地方骑脱,obtainStarter方法通過工廠模式生成了一個(gè)ActivityStarter對(duì)象。真正的代碼跑到了ActivityStarter的execute方法里面:


這樣啟動(dòng)activity的主要流程就跑到ActivityStarter類里面了苍糠,接下來看startActivity方法


此方法里面又調(diào)用了一個(gè)startActivity方法叁丧,而這個(gè)startActivity方法代碼就比較多了,主要對(duì)activity啟動(dòng)的權(quán)限和調(diào)用者等做了校驗(yàn)椿息,不關(guān)注這個(gè)直接走到方法底部還是一個(gè)startActivity方法,下面貼上這個(gè)startActivity方法的代碼


startActivityUnchecked方法坷衍,此方法也比較長寝优,主要對(duì)activity的啟動(dòng)模式和activity棧做了處理,onNewIntent就是在這觸發(fā)的


接下來又跳轉(zhuǎn)到了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法


ActivityStack類的resumeTopActivityUncheckedLocked方法枫耳,這個(gè)方法也比較長乏矾,只關(guān)注最后面的startSpecificActivityLocked方法


ActivityStackSupervisor類startSpecificActivityLocked方法:


startSpecificActivityLocked方法里面對(duì)是應(yīng)用內(nèi)打開activity還是從桌面打開activity做了判斷,如果從桌面打開activity迁杨,此時(shí)應(yīng)用還沒有主進(jìn)程钻心,就會(huì)調(diào)用mService.startProcessLocked方法創(chuàng)建新的進(jìn)程,然后再走startActivity的流程铅协。此處我們關(guān)注realStartActivityLocked方法捷沸,帶上real就證明離真相很近了。


此處是9.0與8.0最大的區(qū)別狐史,改用事物的方式去啟動(dòng)activity了痒给,接下來看事物的提交scheduleTransaction方法


調(diào)用的是ClientTransaction類的schedule方法说墨,接下來看schedule方法


調(diào)用了mClient對(duì)象的方法,mClient是一個(gè)繼承了IApplicationThread接口的實(shí)現(xiàn)類苍柏,是不是很眼熟尼斧,和前面的caller類型一樣,而IApplicationThread的實(shí)現(xiàn)類是ApplicationThread试吁,ActivityThread的內(nèi)部類


好的棺棵,又調(diào)用了ActivityThread類的scheduleTransaction方法,搜索了一下ActivityThread類里面并沒有這個(gè)方法熄捍,這個(gè)時(shí)候不要慌烛恤,看下ActivityThread的父類ClientTransactionHandler,發(fā)現(xiàn)原來這個(gè)方法在父類里面實(shí)現(xiàn)了


又給ActivityThread發(fā)送了一個(gè)消息治唤,接下來看處理這個(gè)消息的代碼


這個(gè)事務(wù)在這又被mTransactionExecutor的方法execute給執(zhí)行了棒动。。宾添。

接下來看TransactionExecutor類的execute方法


在這個(gè)方法里面主要執(zhí)行了兩個(gè)方法船惨,根據(jù)名字判斷executeLifecycleState可能只是改變狀態(tài)而executeCallbacks方法可能更有料,接下來看executeCallbacks方法的代碼


然后繼續(xù)跟item.execute這行代碼缕陕,可以看到item是ClientTransactionItem類的對(duì)象粱锐,那么這個(gè)對(duì)象在哪被復(fù)制的,回到事務(wù)最初創(chuàng)建的地方扛邑,ActivityStackSupervisor類的realStartActivityLocked方法


可以看到此處的clientTransaction調(diào)用了addCallback方法怜浅,而剛才的executeCallbacks方法中出現(xiàn)了clientTransaction.getCallbacks方法,因此這個(gè)LaunchActivityItem就是item蔬崩,接下來看LaunchActivityItem類中的execute方法


可以看到client.handleLaunchActivity這段代碼就是之前8.0中的代碼恶座,兜兜轉(zhuǎn)轉(zhuǎn)這么久,終于回到了這里沥阳,而這個(gè)client就是前面繼承了ClientTransactionHandler的ActivityThread類跨琳,接下來看handleLaunchActivity代碼的實(shí)現(xiàn)


其中的關(guān)鍵方法performLaunchActivity,其中完成了activity實(shí)例的創(chuàng)建桐罕,Application的實(shí)例化脉让,window的依附等操作,activity的生命周期也開始啟動(dòng)功炮,至此activity的創(chuàng)建就算告一段落了溅潜。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市薪伏,隨后出現(xiàn)的幾起案子滚澜,更是在濱河造成了極大的恐慌,老刑警劉巖嫁怀,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件博秫,死亡現(xiàn)場離奇詭異潦牛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)挡育,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門巴碗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人即寒,你說我怎么就攤上這事橡淆。” “怎么了母赵?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵逸爵,是天一觀的道長。 經(jīng)常有香客問我凹嘲,道長师倔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任周蹭,我火速辦了婚禮趋艘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凶朗。我一直安慰自己瓷胧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布棚愤。 她就那樣靜靜地躺著搓萧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宛畦。 梳的紋絲不亂的頭發(fā)上瘸洛,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音次和,去河邊找鬼反肋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛斯够,可吹牛的內(nèi)容都是我干的囚玫。 我是一名探鬼主播喧锦,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼读规,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了燃少?” 一聲冷哼從身側(cè)響起束亏,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阵具,沒想到半個(gè)月后碍遍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體定铜,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年怕敬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揣炕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡东跪,死狀恐怖畸陡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情虽填,我是刑警寧澤丁恭,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站斋日,受9級(jí)特大地震影響牲览,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恶守,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一第献、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧熬的,春花似錦痊硕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至橡伞,卻和暖如春盒揉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背兑徘。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工刚盈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挂脑。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓藕漱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親崭闲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肋联,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

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