由于Activity的啟動涉及大量ipC和Binder方面的知識,因此了解這方面的知識后再來看Activity啟動的相關源碼可能不會那么吃力。
Activity啟動時涉及到的類有IActivityManager相關類, IapplicationThread相關類, ActivityManagerService相關類。
Activity的管理采用binder機制,管理Activity的接口是IActivityManager。ActivityManagerService實現了Activity管理功能,位于system_server進程。從ActivityManagerService提供的接口來看,它負責管理Activity的啟動和生命周期。
ActivityManagerPRoxy對象是ActivityManagerService在普通應用進程的一個代理對象,應用進程通過ActivityManagerProxy對象調用ActivityManagerService提供的功能。應用進程并不會直接創建ActivityManagerProxy對象,而是通過調用ActiviyManagerNative類的工具方法getDefault方法得到ActivityManagerProxy對象。所以在應用進程里通常這樣啟動Activty:
ActivityManagerNative.getDefault().startActivity()
應用進程需要調用ActivityManagerService提供的功能,返過來,ActivityManagerService也需要調用應用進程的回調操作以達到控制和調配應用進程的目的。因此,ActivityManagerService也有一個Binder對象–ApplicationThreadProxy,它是IApplicationThread的代理對象。
ApplicationThread類實現了IApplicationThread接口,實現了管理應用的操作,ApplicationThread對象運行在應用進程里,內部包含了大量啟動和停止Activity的接口,此外還包含了啟動和停止服務的接口。但因為ApplicationThread運行在Binder線程,這些接口方法大多都通過Handler傳給ActivityThread的內部的H來執行。
其實,ApplicationThread是ActivityThread的內部類,H其實是一個Handler,也是ActivityThread的一個內部類,運行在主線程。對于每一個應用程序來說,都有一個ActivityThread來表示一個應用主線程。
 總的來說ActivityManagerService,ApplicationThread和ActivityThread之間的關系。ActivityManagerService可以說是Activity的啟動入口,相當于主國。ApplicationThread相當于外交官,作為ActivityManagerService與ActivityThread之間的信使,負責將ActivityManagerService下達的指令呈給ActivityThread的H來處理,以及將ActivityThread的調用請求傳給ActivityManagerService。ActivityThread則相當于諸侯國,對自己轄區內(應用進程)的Activity有直接的控制權,承擔Activity啟動的大部分工作,但Activity的戶口(ActivityStack)在ActivityManagerService手里。因為ActivityManagerService需要統一調控不同應用進程中的Activity。
 總的來說ActivityManagerService,ApplicationThread和ActivityThread之間的關系。ActivityManagerService可以說是Activity的啟動入口,相當于主國。ApplicationThread相當于外交官,作為ActivityManagerService與ActivityThread之間的信使,負責將ActivityManagerService下達的指令呈給ActivityThread的H來處理,以及將ActivityThread的調用請求傳給ActivityManagerService。ActivityThread則相當于諸侯國,對自己轄區內(應用進程)的Activity有直接的控制權,承擔Activity啟動的大部分工作,但Activity的戶口(ActivityStack)在ActivityManagerService手里。因為ActivityManagerService需要統一調控不同應用進程中的Activity。

系統每一次啟動Activity,先調用Instrumentation的execStartActivity方法。Instrumentation是負責監控Activity與系統的交互操作的,相當于系統運行日志,因此要啟動activity或回調activity的生命周期的方法時,都會先調用Instrumentation相關方法。

經過IPC調用,啟動Activity的指令來到了ActivityManagerService,緊接著AMS調用startActivityAsUser著手Activity的啟動工作。
AMS有一個ActivityStack,負責Activity的調度工作,比如維護回退棧。但ActivityStack內的Activity是抽象成ActivityRecord來管理的。Activity對象不會存在于AMS當中。
ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();由于Activity之間的調度關系受很多因素的影響而變得非常復雜,Google使用了ActivityStack和ActivityStackSupervisor,以及Android 7.0添加的ActivityStarter來管理Activity的調度工作。此三者的調用過程如下圖:

由于它們之間調用過程比較復雜,下面只從挑重點來看。
startActivityMayWait這個方法會創建ActivityRecord對象,再調用startActivityLocked。
這個方法會根據Activity啟動信息(提取封裝到ActivityInfo類中)中的launchMode,flag等屬性來調度ActivityStack中的Task和ActivityRecord。因此這個方法是理解Activity啟動模式的關鍵。
這個方法內部會把前臺處于Resume狀態的Activity變成Pause狀態后才會繼續啟動Activity的邏輯。
將一個Activity變成Pause狀態需要經歷的調用于后面的啟動調用非常相似。
startPausingLocked->ApplicationThread.schedulePauseActivity->mH.sendMessage->ActivityThread.handlePauseActivity->ActivityManagerService.activityPaused->ActivityStack.activityPausedLocked->ActivityStack.completePauseLocked。
在completePauseLocked方法中又一次調用:
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);又回到了resumeTopActivityInnerLocked方法中,這時會調用ActivityStack.startSpecificActivityLocked方法。
這里最后會調用AMS的startProcessLocked,這個方法會先判斷是否已經存在相應的進程,如果不存在則通過遠程調用Zygote進程來孵化出新的應用進程,Zygote進程孵化出新的應用進程后,會執行ActivityThread類的main方法。在該方法里會先準備好Looper和消息隊列,然后調用attach方法將應用進程綁定到ActivityManagerService,然后進入loop循環,不斷地讀取消息隊列里的消息,并分發消息。這個過程在Android的消息機制里已經非常熟悉了。其中attach方法在與AMS綁定的過程中會調用attachApplicationLocked方法。attachApplicationLocked方法有兩個重要的函數調用thread.bindApplication和mMainStack.realStartActivityLocked。thread.bindApplication將應用進程的ApplicationThread對象綁定到ActivityManagerService,也就是說獲得ApplicationThread對象的代理對象。mMainStack.realStartActivityLocked通知應用進程啟動Activity。
然后啟動Activity的代碼邏輯來到了realStartActivityLocked。
app.thread其實就是ApplicationThread在AMS的代理對象,實際上是調用ApplicationThread#scheduleLaunchActivity。接下來Activity的啟動工作就交給應用進程來完成了,別忘了這時候的Activity對象還沒被創建呢。
ApplicationThread接收到來自AMS的Activity啟動命令后,將啟動消息通過H(extends Handler)對象發給ActivityThread。
handleLauchActivity方法中包含了ActivityThread中啟動Activity的幾乎全部邏輯,這個方法內會調用兩個重要的方法:performLaunchActivity和handleResumeActivity。
performLaunchActivity方法內完成了如下工作:
通過類加載器加載Activity對象創建ContextImpl對象并調用activity的attach方法,把上下文變量設置進activity中,創建Window對象和設置WindowManager。回調onCreate,onStart和onRestoreInstanceState方法。handleResumeActivity方法內完成了如下工作:
回調Activity的onResume方法調用WindowManager的addView方法,將前面在attach方法內創建出來的window對象添加到WindowManager當中。關于setContentView:
通常setContentView會在Activity的onCreate方法中調用。但必須要在onCreate中調用嗎?其實setContentView完成了DecorView的創建和繪制,只要在調用WindowManager#addView之前調用setContentView方法也是OK的。因此,最遲到onResume方法中調用setContentView也是可以的。
 完整圖片
 完整圖片
《Android開發藝術探索》 Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
Android應用程序啟動過程源代碼分析
Android應用程序的Activity啟動過程簡要介紹和學習計劃
深入理解Activity啟動流程(一)–Activity啟動的概要流程 深入理解Activity啟動流程(二)–Activity啟動相關類的類圖 深入理解Activity啟動流程(三)–Activity啟動的詳細流程1 深入理解Activity啟動流程(三)–Activity啟動的詳細流程2
startActivity啟動過程分析
新聞熱點
疑難解答