Activity啟動流程

1 前言

日常開發(fā)過程中我們經(jīng)常調(diào)用startActivity(..)啟動新的Activity,那么系統(tǒng)是如何找到這個Activity愈涩,Activity的啟動模式的啟動模式在什么地方發(fā)揮作用,以及如何控制兩個Activity的生命周期的寄狼,這些值得深入源碼中去探索下不见。

2 Activity啟動整體過程

Activity啟動整體流程.png
  1. 點擊桌面app圖標,Launcher進程采用Binder IPC向system_server進程發(fā)起startActivity請求烁竭;
  2. system_server進程接收到請求后,向zygote進程發(fā)送創(chuàng)建新進程的請求吉挣;
  3. zygote進程fork出新的子進程派撕,即App進程婉弹;
  4. App進程通過Binder IPC向system_server進程發(fā)起attach Application請求;
  5. system_server收到請求后腥刹,進行一系列的準備后马胧,再通過Binder IPC向App進程發(fā)送scheduleLaunchActivity請求;
  6. App進程的ApplicationThread收到請求后衔峰,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息佩脊;
  7. 主線程在收到Message后,創(chuàng)建目標Activity垫卤,并回調(diào)Activity.onCreate()等方法威彰;

注意:App與AMS通過Binder進行IPC通信,AMS(SystemServer進程)與zygote通過Socket進行IPC通信穴肘,Zygote創(chuàng)建一個套接字歇盼,監(jiān)聽ams發(fā)過來的fork請求。

2.1 啟動過程涉及的主要類

frameworks/base/services/core/java/com/android/server/am/
  - ActivityManagerService.java
  - ActivityStackSupervisor.java
  - ActivityStack.java
  - ActivityRecord.java
  - ProcessRecord.java

frameworks/base/core/java/android/app/
  - IActivityManager.java
  - ActivityManagerNative.java (內(nèi)含ActivityManagerProxy)
  - ActivityManager.java

  - IApplicationThread.java
  - ApplicationThreadNative.java (內(nèi)含ApplicationThreadProxy)
  - ActivityThread.java (內(nèi)含ApplicationThread)
  - Instrumentation.java
  - ContextImpl.java
  • ActivityManagerServices
    簡稱AMS评抚,服務(wù)端對象豹缀,負責系統(tǒng)中所有Activity的生命周期。

  • ActivityStackSupervisor
    管理activity任務(wù)棧慨代,內(nèi)部管理了mHomeStack邢笙、mFocusedStack和mLastFocusedStack三個Activity棧。其中侍匙,mHomeStack管理的是Launcher相關(guān)的Activity棧氮惯;mFocusedStack管理的是當前顯示在前臺Activity的Activity棧;mLastFocusedStack管理的是上一次顯示在前臺Activity的Activity棧想暗。

  • ActivityStack
    Activity在AMS的棧管理妇汗,用來記錄已經(jīng)啟動的Activity的先后關(guān)系,狀態(tài)信息等说莫。通過ActivityStack決定是否需要啟動新的進程杨箭。

  • ActivityRecord
    ActivityStack的管理對象,每個Activity在AMS對應(yīng)一個ActivityRecord储狭,來記錄Activity的狀態(tài)以及其他的管理信息互婿,其實就是服務(wù)器端的Activity對象的映像。

  • TaskRecord
    AMS抽象出來的一個“任務(wù)”的概念晶密,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord模她。AMS用TaskRecord確保Activity啟動和退出的順序稻艰。如果你清楚Activity的4種launchMode,那么對這個概念應(yīng)該不陌生侈净。


  • ApplicationThread
    用來實現(xiàn)AMS和ActivityThread之間的交互尊勿。在AMS需要管理相關(guān)Application中的Activity的生命周期時僧凤,通過ApplicationThread的代理對象與ActivityThread通訊。

  • ApplicationThreadProxy
    ApplicationThread 在服務(wù)端的代理元扔,AMS就是通過該代理與ActivityThread進行通信的躯保。

  • ActivityThread
    App的真正入口,當開啟App之后澎语,會調(diào)用main()開始運行途事,開啟消息循環(huán)隊列,這就是傳說中的UI線程或者叫主線程擅羞。與ActivityManagerServices配合尸变,一起完成Activity的管理工作。

  • Instrumentation
    儀表盤减俏,每一個應(yīng)用程序只有一個Instrumentation對象召烂,每個Activity內(nèi)都有一個對該對象的引用。負責調(diào)用
    Activity和Application生命周期娃承。測試用到這個類比較多奏夫。AMS是董事會,負責指揮和調(diào)度的历筝,ActivityThread是老板酗昼,雖然說家里的事自己說了算,但是需要聽從AMS的指揮漫谷,而Instrumentation則是老板娘仔雷,負責家里的大事小事,但是一般不拋頭露面舔示,聽一家之主ActivityThread的安排碟婆。

3 Activity啟動過程階段

Launcher啟動Activity過程.png

Activity啟動流程(從Launcher開始):
第一階段: Launcher通知AMS要啟動新的Activity(在Launcher所在的進程執(zhí)行)

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

第二階段:AMS先校驗一下Activity的正確性,如果正確的話惕稻,會暫存一下Activity的信息竖共。然后,AMS會通知Launcher程序pause Activity(在AMS所在進程執(zhí)行)

  • ctivityManagerService.startActivity
  • ActivityManagerService.startActivityAsUser
  • ActivityStackSupervisor.startActivityMayWait
  • ActivityStackSupervisor.startActivityLocked :檢查有沒有在AndroidManifest中注冊
  • ActivityStackSupervisor.startActivityUncheckedLocked
  • ActivityStack.startActivityLocked :判斷是否需要創(chuàng)建一個新的任務(wù)來啟動Activity俺祠。
  • ActivityStack.resumeTopActivityLocked :獲取棧頂?shù)腶ctivity公给,并通知Launcher應(yīng)該pause掉這個Activity以便啟動新的activity。
  • ActivityStack.startPausingLocked
  • ApplicationThreadProxy.schedulePauseActivity

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

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

第四階段:檢查activity所在進程是否存在淌铐,如果存在,就直接通知這個進程蔫缸,在該進程中啟動Activity腿准;不存在的話,會調(diào)用Process.start創(chuàng)建一個新進程(執(zhí)行在AMS進程)

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

第五階段: 創(chuàng)建ActivityThread實例街望,執(zhí)行一些初始化操作,并綁定Application弟跑。如果Application不存在灾前,會調(diào)用LoadedApk.makeApplication創(chuàng)建一個新的Application對象。之后進入Loop循環(huán)孟辑。(執(zhí)行在新創(chuàng)建的app進程)

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

第六階段:處理新的應(yīng)用進程發(fā)出的創(chuàng)建進程完成的通信請求哎甲,并通知新應(yīng)用程序進程啟動目標Activity組件(執(zhí)行在AMS進程)

  • ActivityManagerService.attachApplication //AMS綁定本地ApplicationThread對象,后續(xù)通過ApplicationThreadProxy來通信扑浸。
  • ActivityManagerService.attachApplicationLocked
  • ActivityStack.realStartActivityLocked //真正要啟動Activity了烧给!
  • ApplicationThreadProxy.scheduleLaunchActivity //AMS通過ATP通知app進程啟動Activity

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

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

4 Activity啟動代碼分析

Activity啟動流程詳圖.png

Activity的啟動過程主要會涉及五個進程:Launcher進程喝噪、System_server進程础嫡、當前的前臺進程、待啟動的Activity所在進程酝惧、Zygote進程榴鼎, 在上圖中已有所體現(xiàn)。
具體源碼分析見參考資料[5]和[10]

參考資料:

[1] Activity啟動流程
[2] Activity 啟動全過程解析
[3] Android的Activity啟動流程分析
[4] Activity 啟動流程
[5] 一張圖表示Activity啟動流程-- Activity啟動流程詳解 ★★
[6] 3分鐘看懂Activity啟動流程
[7] 說說Activity的啟動流程
[8] Android進程啟動過程 & Activity顯示過程
[9] 庖丁解牛 Activity 啟動流程
[10] startActivity啟動過程分析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載晚唇,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者巫财。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哩陕,隨后出現(xiàn)的幾起案子平项,更是在濱河造成了極大的恐慌,老刑警劉巖悍及,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闽瓢,死亡現(xiàn)場離奇詭異,居然都是意外死亡心赶,警方通過查閱死者的電腦和手機扣讼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缨叫,“玉大人椭符,你說我怎么就攤上這事〕芾眩” “怎么了销钝?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琐簇。 經(jīng)常有香客問我蒸健,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任纵装,我火速辦了婚禮,結(jié)果婚禮上据某,老公的妹妹穿的比我還像新娘橡娄。我一直安慰自己,他們只是感情好癣籽,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布挽唉。 她就那樣靜靜地躺著,像睡著了一般筷狼。 火紅的嫁衣襯著肌膚如雪瓶籽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天埂材,我揣著相機與錄音塑顺,去河邊找鬼。 笑死俏险,一個胖子當著我的面吹牛严拒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竖独,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼裤唠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了莹痢?” 一聲冷哼從身側(cè)響起种蘸,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竞膳,沒想到半個月后航瞭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡顶猜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年沧奴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片长窄。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡滔吠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挠日,到底是詐尸還是另有隱情疮绷,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布嚣潜,位于F島的核電站冬骚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜只冻,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一庇麦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喜德,春花似錦山橄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萌衬,卻和暖如春饮醇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秕豫。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工朴艰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人混移。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓呵晚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沫屡。 傳聞我的和親對象是個殘疾皇子饵隙,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

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