Activity啟動(dòng)流程

引言

Activity啟動(dòng)流程很多文章都已經(jīng)說過了额嘿,這里說一下自己的理解蓝角。
Activity啟動(dòng)流程分兩種:

  • 一種是啟動(dòng)正在運(yùn)行的app的Activity肄方,即啟動(dòng)子Activity稚矿。如無特殊聲明默認(rèn)和啟動(dòng)該activity的activity處于同一進(jìn)程掏熬。如果有聲明在一個(gè)新的進(jìn)程中搀崭,則處于兩個(gè)進(jìn)程叨粘。
  • 一種是打開新的app,即為L(zhǎng)auncher啟動(dòng)新的Activity瘤睹。

后邊啟動(dòng)Activity的流程是一樣的宣鄙,區(qū)別是前邊判斷進(jìn)程是否存在的那部分。

Activity啟動(dòng)的前提是已經(jīng)開機(jī)默蚌,各項(xiàng)進(jìn)程和AMS等服務(wù)已經(jīng)初始化完成冻晤,在這里也提一下那些內(nèi)容。

Activity啟動(dòng)之前的一些事情

  • init進(jìn)程:init是所有l(wèi)inux程序的起點(diǎn)绸吸,是Zygote的父進(jìn)程鼻弧。解析init.rc孵化出Zygote進(jìn)程。

  • Zygote進(jìn)程:Zygote是所有Java進(jìn)程的父進(jìn)程锦茁,所有的App進(jìn)程都是由Zygote進(jìn)程fork生成的攘轩。

  • SystemServer進(jìn)程:System Server是Zygote孵化的第一個(gè)進(jìn)程。SystemServer負(fù)責(zé)啟動(dòng)和管理整個(gè)Java framework码俩,包含AMS度帮,PMS等服務(wù)。

  • Launcher:Zygote進(jìn)程孵化的第一個(gè)App進(jìn)程是Launcher稿存。

    1.init進(jìn)程是什么笨篷?

    Android是基于linux系統(tǒng)的,手機(jī)開機(jī)之后瓣履,linux內(nèi)核進(jìn)行加載率翅。加載完成之后會(huì)啟動(dòng)init進(jìn)程。
    init進(jìn)程會(huì)啟動(dòng)ServiceManager袖迎,孵化一些守護(hù)進(jìn)程冕臭,并解析init.rc孵化Zygote進(jìn)程。

    2.Zygote進(jìn)程是什么燕锥?

    所有的App進(jìn)程都是由Zygote進(jìn)程fork生成的辜贵,包括SystemServer進(jìn)程。Zygote初始化后归形,會(huì)注冊(cè)一個(gè)等待接受消息的socket托慨,OS層會(huì)采用socket進(jìn)行IPC通信。

    3.為什么是Zygote來孵化進(jìn)程连霉,而不是新建進(jìn)程呢榴芳?

    每個(gè)應(yīng)用程序都是運(yùn)行在各自的Dalvik虛擬機(jī)中,應(yīng)用程序每次運(yùn)行都要重新初始化和啟動(dòng)虛擬機(jī)跺撼,這個(gè)過程會(huì)耗費(fèi)很長(zhǎng)時(shí)間窟感。Zygote會(huì)把已經(jīng)運(yùn)行的虛擬機(jī)的代碼和內(nèi)存信息共享,起到一個(gè)預(yù)加載資源和類的作用歉井,從而縮短啟動(dòng)時(shí)間柿祈。

Activity啟動(dòng)階段

涉及到的概念

  • 進(jìn)程:Android系統(tǒng)為每個(gè)APP分配至少一個(gè)進(jìn)程
  • IPC:跨進(jìn)程通信,Android中采用Binder機(jī)制哩至。

涉及到的類

  • ActivityStack:Activity在AMS的棧管理躏嚎,用來記錄已經(jīng)啟動(dòng)的Activity的先后關(guān)系,狀態(tài)信息等菩貌。通過ActivityStack決定是否需要啟動(dòng)新的進(jìn)程卢佣。
  • ActivitySupervisor:管理 activity 任務(wù)棧
  • ActivityThread:ActivityThread 運(yùn)行在UI線程(主線程),App的真正入口箭阶。
  • ApplicationThread:用來實(shí)現(xiàn)AMS和ActivityThread之間的交互虚茶。
  • ApplicationThreadProxy:ApplicationThread 在服務(wù)端的代理。AMS就是通過該代理與ActivityThread進(jìn)行通信的仇参。
  • IActivityManager:繼承與IInterface接口嘹叫,抽象出跨進(jìn)程通信需要實(shí)現(xiàn)的功能
  • AMN:運(yùn)行在server端(SystemServer進(jìn)程)。實(shí)現(xiàn)了Binder類诈乒,具體功能由子類AMS實(shí)現(xiàn)罩扇。
  • AMS:AMN的子類,負(fù)責(zé)管理四大組件和進(jìn)程怕磨,包括生命周期和狀態(tài)切換喂饥。AMS因?yàn)橐蛈i交互,所以極其復(fù)雜肠鲫,涉及window仰泻。
  • AMP:AMS的client端代理(app進(jìn)程)。了解Binder知識(shí)可以比較容易理解server端的stub和client端的proxy滩届。AMP和AMS通過Binder通信集侯。
  • Instrumentation:儀表盤,負(fù)責(zé)調(diào)用Activity和Application生命周期帜消。測(cè)試用到這個(gè)類比較多棠枉。

流程圖

這個(gè)圖來源自網(wǎng)上,之前也看過很多類似講流程的文章泡挺,但是大都是片段的辈讶。這個(gè)圖是目前看到的最全的,自己去畫一下也應(yīng)該不會(huì)比這個(gè)全了娄猫,所以在這里直接引用一下贱除,可以去瀏覽器上放大看生闲。

涉及到的進(jìn)程

  • Launcher所在的進(jìn)程
  • AMS所在的SystemServer進(jìn)程
  • 要啟動(dòng)的Activity所在的app進(jìn)程

如果是啟動(dòng)根Activity,就涉及上述三個(gè)進(jìn)程月幌。
如果是啟動(dòng)子Activity碍讯,那么就只涉及AMS進(jìn)程和app所在進(jìn)程。

具體流程

  • Launcher:Launcher通知AMS要啟動(dòng)activity扯躺。
    • startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity
  • AMS:PMS的resoveIntent驗(yàn)證要啟動(dòng)activity是否匹配捉兴。
    • 如果匹配,通過ApplicationThread發(fā)消息給Launcher所在的主線程录语,暫停當(dāng)前Activity(Launcher);
  • 暫停完倍啥,在該activity還不可見時(shí),通知AMS澎埠,根據(jù)要啟動(dòng)的Activity配置ActivityStack虽缕。然后判斷要啟動(dòng)的Activity進(jìn)程是否存在?
    • 存在:發(fā)送消息LAUNCH_ACTIVITY給需要啟動(dòng)的Activity主線程,執(zhí)行handleLaunchActivity
    • 不存在:通過socket向zygote請(qǐng)求創(chuàng)建進(jìn)程蒲稳。進(jìn)程啟動(dòng)后彼宠,ActivityThread.attach
  • 判斷Application是否存在,若不存在弟塞,通過LoadApk.makeApplication創(chuàng)建一個(gè)凭峡。在主線程中通過thread.attach方法來關(guān)聯(lián)ApplicationThread。
  • 在通過ActivityStackSupervisor來獲取當(dāng)前需要顯示的ActivityStack决记。
  • 繼續(xù)通過ApplicationThread來發(fā)送消息給主線程的Handler來啟動(dòng)Activity(handleLaunchActivity)摧冀。
  • handleLauchActivity:調(diào)用了performLauchActivity,里邊Instrumentation生成了新的activity對(duì)象系宫,繼續(xù)調(diào)用activity生命周期索昂。

IPC過程:

雙方都是通過對(duì)方的代理對(duì)象來進(jìn)行通信。
1.app和AMS通信:app通過本進(jìn)程的AMP和AMS進(jìn)行Binder通信
2.AMS和新app通信:通過ApplicationThreadProxy來通信扩借,并不直接和ActivityThread通信

參考函數(shù)流程

Activity啟動(dòng)流程(從Launcher開始):

第一階段: Launcher通知AMS要啟動(dòng)新的Activity(在Launcher所在的進(jìn)程執(zhí)行)

  • Launcher.startActivitySafely //首先Launcher發(fā)起啟動(dòng)Activity的請(qǐng)求
  • Activity.startActivity
  • Activity.startActivityForResult
  • Instrumentation.execStartActivity //交由Instrumentation代為發(fā)起請(qǐng)求
  • ActivityManager.getService().startActivity //通過IActivityManagerSingleton.get()得到一個(gè)AMP代理對(duì)象
  • ActivityManagerProxy.startActivity //通過AMP代理通知AMS啟動(dòng)activity

第二階段:AMS先校驗(yàn)一下Activity的正確性椒惨,如果正確的話,會(huì)暫存一下Activity的信息潮罪。然后罐寨,AMS會(huì)通知Launcher程序pause Activity(在AMS所在進(jìn)程執(zhí)行)

  • ActivityManagerService.startActivity
  • ActivityManagerService.startActivityAsUser
  • ActivityStackSupervisor.startActivityMayWait
  • ActivityStackSupervisor.startActivityLocked :檢查有沒有在AndroidManifest中注冊(cè)
  • ActivityStackSupervisor.startActivityUncheckedLocked
  • ActivityStack.startActivityLocked :判斷是否需要?jiǎng)?chuàng)建一個(gè)新的任務(wù)來啟動(dòng)Activity盯滚。
  • ActivityStack.resumeTopActivityLocked :獲取棧頂?shù)腶ctivity鳍悠,并通知Launcher應(yīng)該pause掉這個(gè)Activity以便啟動(dòng)新的activity瞎颗。
  • ActivityStack.startPausingLocked
  • ApplicationThreadProxy.schedulePauseActivity

第三階段: pause Launcher的Activity,并通知AMS已經(jīng)paused(在Launcher所在進(jìn)程執(zhí)行)

  • ApplicationThread.schedulePauseActivity
  • ActivityThread.queueOrSendMessage
  • H.handleMessage
  • ActivityThread.handlePauseActivity
  • ActivityManagerProxy.activityPaused

第四階段:檢查activity所在進(jìn)程是否存在何恶,如果存在孽锥,就直接通知這個(gè)進(jìn)程,在該進(jìn)程中啟動(dòng)Activity;不存在的話惜辑,會(huì)調(diào)用Process.start創(chuàng)建一個(gè)新進(jìn)程(執(zhí)行在AMS進(jìn)程)

  • ActivityManagerService.activityPaused
  • ActivityStack.activityPaused
  • ActivityStack.completePauseLocked
  • ActivityStack.resumeTopActivityLocked
  • ActivityStack.startSpecificActivityLocked
  • ActivityManagerService.startProcessLocked
  • Process.start //在這里創(chuàng)建了新進(jìn)程唬涧,新的進(jìn)程會(huì)導(dǎo)入ActivityThread類,并執(zhí)行它的main函數(shù)

第五階段: 創(chuàng)建ActivityThread實(shí)例盛撑,執(zhí)行一些初始化操作碎节,并綁定Application。如果Application不存在撵彻,會(huì)調(diào)用LoadedApk.makeApplication創(chuàng)建一個(gè)新的Application對(duì)象钓株。之后進(jìn)入Loop循環(huán)实牡。(執(zhí)行在新創(chuàng)建的app進(jìn)程)

  • ActivityThread.main
  • ActivityThread.attach(false) //聲明不是系統(tǒng)進(jìn)程
  • ActivityManagerProxy.attachApplication

第六階段:處理新的應(yīng)用進(jìn)程發(fā)出的創(chuàng)建進(jìn)程完成的通信請(qǐng)求陌僵,并通知新應(yīng)用程序進(jìn)程啟動(dòng)目標(biāo)Activity組件(執(zhí)行在AMS進(jìn)程)

  • ActivityManagerService.attachApplication //AMS綁定本地ApplicationThread對(duì)象,后續(xù)通過ApplicationThreadProxy來通信创坞。
  • ActivityManagerService.attachApplicationLocked
  • ActivityStack.realStartActivityLocked //真正要啟動(dòng)Activity了碗短!
  • ApplicationThreadProxy.scheduleLaunchActivity //AMS通過ATP通知app進(jìn)程啟動(dòng)Activity

第七階段: 加載MainActivity類,調(diào)用onCreate聲明周期方法(執(zhí)行在新啟動(dòng)的app進(jìn)程)

  • ApplicationThread.scheduleLaunchActivity //ApplicationThread發(fā)消息給AT
  • ActivityThread.queueOrSendMessage
  • H.handleMessage //AT的Handler來處理接收到的LAUNCH_ACTIVITY的消息
  • ActivityThread.handleLaunchActivity
  • ActivityThread.performLaunchActivity
  • Instrumentation.newActivity //調(diào)用Instrumentation類來新建一個(gè)Activity對(duì)象
  • Instrumentation.callActivityOnCreate
  • MainActivity.onCreate
  • ActivityThread.handleResumeActivity
  • AMP.activityResumed
  • AMS.activityResumed(AMS進(jìn)程)

參考文章

http://gityuan.com/2016/03/12/start-activity/
https://blog.csdn.net/luoshengyang/article/details/6689748

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末题涨,一起剝皮案震驚了整個(gè)濱河市偎谁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纲堵,老刑警劉巖巡雨,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異席函,居然都是意外死亡铐望,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門茂附,熙熙樓的掌柜王于貴愁眉苦臉地迎上來正蛙,“玉大人,你說我怎么就攤上這事营曼∑寡椋” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蒂阱,是天一觀的道長(zhǎng)锻全。 經(jīng)常有香客問我,道長(zhǎng)录煤,這世上最難降的妖魔是什么虱痕? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮辐赞,結(jié)果婚禮上部翘,老公的妹妹穿的比我還像新娘。我一直安慰自己响委,他們只是感情好新思,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布窖梁。 她就那樣靜靜地躺著,像睡著了一般夹囚。 火紅的嫁衣襯著肌膚如雪纵刘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天荸哟,我揣著相機(jī)與錄音假哎,去河邊找鬼。 笑死鞍历,一個(gè)胖子當(dāng)著我的面吹牛舵抹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劣砍,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惧蛹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了刑枝?” 一聲冷哼從身側(cè)響起香嗓,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎装畅,沒想到半個(gè)月后靠娱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掠兄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年像云,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徽千。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苫费,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出双抽,到底是詐尸還是另有隱情百框,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布牍汹,位于F島的核電站铐维,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏慎菲。R本人自食惡果不足惜嫁蛇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望露该。 院中可真熱鬧睬棚,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至底靠,卻和暖如春害晦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暑中。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工壹瘟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鳄逾。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓稻轨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親严衬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子澄者,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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