當前位置:
首頁 > 最新 > 你知道APP從啟動到主頁面顯示經歷了哪些過程嗎?

你知道APP從啟動到主頁面顯示經歷了哪些過程嗎?

作者博客

http://www.jianshu.com/u/0fa6f5d09040

文章目錄

前言

流程概述

理論基礎

啟動流程

前言

本文以圖文並茂的形式簡單介紹一個APP從啟動到主頁面顯示經歷了哪些流程,以及實現的原理。不介紹具體源碼,僅僅構建一個大體框架。

1

流程概述

啟動流程:

點擊桌面App圖標,Launcher進程採用Binder IPC向system_server進程發起startActivity請求;

system_server進程接收到請求後,向zygote進程發送創建進程的請求;

Zygote進程fork出新的子進程,即App進程;

App進程,通過Binder IPC向sytem_server進程發起attachApplication請求;

system_server進程在收到請求後,進行一系列準備工作後,再通過binder IPC向App進程發送scheduleLaunchActivity請求;

App進程的binder線程(ApplicationThread)在收到請求後,通過handler向主線程發送LAUNCH_ACTIVITY消息;

主線程在收到Message後,通過發射機制創建目標Activity,並回調Activity.onCreate()等方法。

到此,App便正式啟動,開始進入Activity生命周期,執行完onCreate/onStart/onResume方法,UI渲染結束後便可以看到App的主界面。

上面的一些列步驟簡單介紹了一個APP啟動到主頁面顯示的過程,可能這些流程中的一些術語看的有些懵,什麼是Launcher,什麼是zygote,什麼是applicationThread.....

下面我們一一介紹。

2

理論基礎

1.zygote

zygote意為「受精卵「。Android是基於Linux系統的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。

在Android系統裡面,zygote是一個進程的名字。Android是基於Linux System的,當你的手機開機的時候,Linux的內核載入完成之後就會啟動一個叫「init「的進程。在Linux System裡面,所有的進程都是由init進程fork出來的,我們的zygote進程也不例外。

我們都知道,每一個App其實都是

一個單獨的dalvik虛擬機

一個單獨的進程

所以當系統裡面的第一個zygote進程運行之後,在這之後再開啟App,就相當於開啟一個新的進程。而為了實現資源共用和更快的啟動速度,Android系統開啟新進程的方式,是通過fork第一個zygote進程實現的。所以說,除了第一個zygote進程,其他應用所在的進程都是zygote的子進程,這下你明白為什麼這個進程叫「受精卵」了吧?因為就像是一個受精卵一樣,它能快速的分裂,並且產生遺傳物質一樣的細胞!

2.system_server

SystemServer也是一個進程,而且是由zygote進程fork出來的。

知道了SystemServer的本質,我們對它就不算太陌生了,這個進程是Android Framework裡面兩大非常重要的進程之一——另外一個進程就是上面的zygote進程。

為什麼說SystemServer非常重要呢?因為系統裡面重要的服務都是在這個進程裡面開啟的,比如

ActivityManagerService、PackageManagerService、WindowManagerService等等。

3.ActivityManagerService

ActivityManagerService,簡稱AMS,服務端對象,負責系統中所有Activity的生命周期。

ActivityManagerService進行初始化的時機很明確,就是在SystemServer進程開啟的時候,就會初始化ActivityManagerService。

下面介紹下Android系統裡面的伺服器和客戶端的概念。

其實伺服器客戶端的概念不僅僅存在於Web開發中,在Android的框架設計中,使用的也是這一種模式。伺服器端指的就是所有App共用的系統服務,比如我們這裡提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎的系統服務是被所有的App公用的,當某個App想實現某個操作的時候,要告訴這些系統服務,比如你想打開一個App,那麼我們知道了包名和MainActivity類名之後就可以打開

但是,我們的App通過調用startActivity()並不能直接打開另外一個App,這個方法會通過一系列的調用,最後還是告訴AMS說:「我要打開這個App,我知道他的住址和名字,你幫我打開吧!」所以是AMS來通知zygote進程來fork一個新進程,來開啟我們的目標App的。這就像是瀏覽器想要打開一個超鏈接一樣,瀏覽器把網頁地址發送給伺服器,然後還是伺服器把需要的資源文件發送給客戶端的。

知道了Android Framework的客戶端伺服器架構之後,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通信呢?

App與AMS通過Binder進行IPC通信,AMS(SystemServer進程)與zygote通過Socket進行IPC通信。後面具體介紹。

那麼AMS有什麼用呢?在前面我們知道了,如果想打開一個App的話,需要AMS去通知zygote進程,除此之外,其實所有的Activity的開啟、暫停、關閉都需要AMS來控制,所以我們說,AMS負責系統中所有Activity的生命周期。

在Android系統中,任何一個Activity的啟動都是由AMS和應用程序進程(主要是ActivityThread)相互配合來完成的。AMS服務統一調度系統中所有進程的Activity啟動,而每個Activity的啟動過程則由其所屬的進程具體來完成。

4.Launcher

當我們點擊手機桌面上的圖標的時候,App就由Launcher開始啟動了。但是,你有沒有思考過Launcher到底是一個什麼東西?

Launcher本質上也是一個應用程序,和我們的App一樣,也是繼承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

Launcher實現了點擊、長按等回調介面,來接收用戶的輸入。既然是普通的App,那麼我們的開發經驗在這裡就仍然適用,比如,我們點擊圖標的時候,是怎麼開啟的應用呢?捕捉圖標點擊事件,然後startActivity()發送對應的Intent請求唄!是的,Launcher也是這麼做的,就是這麼easy!

5.Instrumentation和ActivityThread

每個Activity都持有Instrumentation對象的一個引用,但是整個進程只會存在一個Instrumentation對象。

Instrumentation這個類裡面的方法大多數和Application和Activity有關,這個類就是完成對Application和Activity初始化和生命周期的工具類。Instrumentation這個類很重要,對Activity生命周期方法的調用根本就離不開他,他可以說是一個大管家。

ActivityThread,依賴於UI線程。App和AMS是通過Binder傳遞信息的,那麼ActivityThread就是專門與AMS的外交工作的。

6.ApplicationThread

前面我們已經知道了App的啟動以及Activity的顯示都需要AMS的控制,那麼我們便需要和服務端的溝通,而這個溝通是雙向的。

客戶端-->服務端

而且由於繼承了同樣的公共介面類,ActivityManagerProxy提供了與ActivityManagerService一樣的函數原型,使用戶感覺不出Server是運行在本地還是遠端,從而可以更加方便的調用這些重要的系統服務。

服務端-->客戶端

還是通過Binder通信,不過是換了另外一對,換成了ApplicationThread和ApplicationThreadProxy。

他們也都實現了相同的介面IApplicationThread

關於Binder通信,可以參考這兩篇文章理解一下:關於AIDL使用和Binder機制詳解(http://www.jianshu.com/p/e3293b8346ab)

好了,前面羅里吧嗦的一大堆,介紹了一堆名詞,可能不太清楚,沒關係,下面結合流程圖介紹。

3

啟動流程

1.創建進程

先從Launcher的startActivity()方法,通過Binder通信,調用ActivityManagerService的startActivity方法。

一系列折騰,最後調用startProcessLocked()方法來創建新的進程。

該方法會通過前面講到的socket通道傳遞參數給Zygote進程。Zygote孵化自身。調用ZygoteInit.main()方法來實例化ActivityThread對象並最終返回新進程的pid。

調用ActivityThread.main()方法,ActivityThread隨後依次調用Looper.prepareLoop()和Looper.loop()來開啟消息循環。

方法調用流程圖如下:

更直白的流程解釋:

App發起進程:當從桌面啟動應用,則發起進程便是Launcher所在進程;當從某App內啟動遠程進程,則發送進程便是該App所在進程。發起進程先通過binder發送消息給system_server進程;

system_server進程:調用Process.start()方法,通過socket向zygote進程發送創建新進程的請求;

zygote進程:在執行ZygoteInit.main()後便進入runSelectLoop()循環體內,當有客戶端連接時便會執行ZygoteConnection.runOnce()方法,再經過層層調用後fork出新的應用進程;

新進程:執行handleChildProc方法,最後調用ActivityThread.main()方法。

2.綁定Application

上面創建進程後,執行ActivityThread.main()方法,隨後調用attach()方法。

將進程和指定的Application綁定起來。這個是通過上節的ActivityThread對象中調用bindApplication()方法完成的。該方法發送一個BIND_APPLICATION的消息到消息隊列中, 最終通過handleBindApplication()方法處理該消息. 然後調用makeApplication()方法來載入App的classes到內存中。

方法調用流程圖如下:

更直白的流程解釋:

(如不懂AMS,ATP等名詞,後面有解釋)

3.顯示Activity界面

經過前兩個步驟之後, 系統已經擁有了該application的進程。 後面的調用順序就是普通的從一個已經存在的進程中啟動一個新進程的activity了。

實際調用方法是realStartActivity(), 它會調用application線程對象中的scheduleLaunchActivity()發送一個LAUNCH_ACTIVITY消息到消息隊列中, 通過 handleLaunchActivity()來處理該消息。在 handleLaunchActivity()通過performLaunchActiivty()方法回調Activity的onCreate()方法和onStart()方法,然後通過handleResumeActivity()方法,回調Activity的onResume()方法,最終顯示Activity界面。

更直白的流程解釋:

4

Binder通信

簡稱:

ATP: ApplicationThreadProxy

AT: ApplicationThread

AMP: ActivityManagerProxy

AMS: ActivityManagerService

圖解:

system_server進程中調用startProcessLocked方法,該方法最終通過socket方式,將需要創建新進程的消息告知Zygote進程,並阻塞等待Socket返回新創建進程的pid;

Zygote進程接收到system_server發送過來的消息, 則通過fork的方法,將zygote自身進程複製生成新的進程,並將ActivityThread相關的資源載入到新進程app process,這個進程可能是用於承載activity等組件;

在新進程app process向servicemanager查詢system_server進程中binder服務端AMS, 獲取相對應的Client端,也就是AMP. 有了這一對binder c/s對, 那麼app process便可以通過binder向跨進程system_server發送請求,即attachApplication()

system_server進程接收到相應binder操作後,經過多次調用,利用ATP向app process發送binder請求, 即bindApplication.

system_server擁有ATP/AMS, 每一個新創建的進程都會有一個相應的AT/AMP,從而可以跨進程 進行相互通信. 這便是進程創建過程的完整生態鏈。

以上大概介紹了一個APP從啟動到主頁面顯示經歷的流程,主要從宏觀角度介紹了其過程,具體可結合源碼理解。

參考文章:

startActivity啟動過程分析

理解Android進程創建流程

[譯]Android Application啟動流程分析

【凱子哥帶你學Framework】Activity啟動過程全解析

分享是一種美德,分享你的方案,讓大家學習,共同進步,歡迎投稿。


點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 碼蛋 的精彩文章:

史上最詳細仿QQ消息拖拽粘性效果
召喚,光能使者-玩轉PathMeasure
技術分享 你不是一個人
不管出彩還是出局,要管得住初心
如何在移動開發者的寒冬中破冰而出?

TAG:碼蛋 |