[譯]Android Application啟動(dòng)流程分析

譯者注:
原文分成兩個(gè)部分, 鏈接如下:
http://multi-core-dump.blogspot.com/2010/04/android-application-launch.html
http://multi-core-dump.blogspot.com/2010/04/android-application-launch-part-2.html
本文合二為一, 章節(jié)標(biāo)題由譯者加注.

作者曾經(jīng)在高通的Android性能組工作, 主要工作是優(yōu)化Android Application的啟動(dòng)時(shí)間.

1, App基礎(chǔ)理論

要想優(yōu)化App啟動(dòng)時(shí)間, 第一步就是了解App啟動(dòng)進(jìn)程的工作原理. 有幾個(gè)基礎(chǔ)理論:

Android Application與其他移動(dòng)平臺(tái)有兩個(gè)重大不同點(diǎn):

  1. 每個(gè)Android App都在一個(gè)獨(dú)立空間里, 意味著其運(yùn)行在一個(gè)單獨(dú)的進(jìn)程中, 擁有自己的VM, 被系統(tǒng)分配一個(gè)唯一的user ID.
  2. Android App由很多不同組件組成, 這些組件還可以啟動(dòng)其他App的組件. 因此, Android App并沒有一個(gè)類似程序入口的main()方法.

Android Application組件包括:

  • Activities: 前臺(tái)界面, 直接面向User, 提供UI和操作.
  • Services: 后臺(tái)任務(wù).
  • Broadcast Receivers: 廣播接收者.
  • Contexnt Providers: 數(shù)據(jù)提供者.

Android進(jìn)程與Linux進(jìn)程一樣. 默認(rèn)情況下, 每個(gè)apk運(yùn)行在自己的Linux進(jìn)程中. 另外, 默認(rèn)一個(gè)進(jìn)程里面只有一個(gè)線程---主線程. 這個(gè)主線程中有一個(gè)Looper實(shí)例, 通過調(diào)用Looper.loop()從Message隊(duì)列里面取出Message來做相應(yīng)的處理.

那么, 這個(gè)進(jìn)程何時(shí)啟動(dòng)的呢?
簡單的說, 進(jìn)程在其需要的時(shí)候被啟動(dòng). 任意時(shí)候, 當(dāng)用戶或者其他組件調(diào)取你的apk中的任意組件時(shí), 如果你的apk沒有運(yùn)行, 系統(tǒng)會(huì)為其創(chuàng)建一個(gè)新的進(jìn)程并啟動(dòng). 通常, 這個(gè)進(jìn)程會(huì)持續(xù)運(yùn)行直到被系統(tǒng)殺死. 關(guān)鍵是: 進(jìn)程是在被需要的時(shí)候才創(chuàng)建的.

舉個(gè)例子, 如果你點(diǎn)擊email中的超鏈接, 會(huì)在瀏覽器里面打開一個(gè)網(wǎng)頁. Email App和瀏覽器App是兩個(gè)不同的App, 運(yùn)行在不同的進(jìn)程中. 這次點(diǎn)擊事件促使Android系統(tǒng)去創(chuàng)建了一個(gè)新的進(jìn)程來實(shí)例化瀏覽器的組件.

首先, 讓我們快速看下Android啟動(dòng)流程. 與眾多基于Linux內(nèi)核的系統(tǒng)類似, 啟動(dòng)系統(tǒng)時(shí), bootloader啟動(dòng)內(nèi)核和init進(jìn)程. init進(jìn)程分裂出更多名為"daemons(守護(hù)進(jìn)程)"的底層的Linux進(jìn)程, 諸如android debug deamon, USB deamon等. 這些守護(hù)進(jìn)程處理底層硬件相關(guān)的接口.

隨后, init進(jìn)程會(huì)啟動(dòng)一個(gè)非常有意思的進(jìn)程---"Zygote". 顧名思義, 這是一個(gè)Android平臺(tái)的非?;A(chǔ)的進(jìn)程. 這個(gè)進(jìn)程初始化了第一個(gè)VM, 并且預(yù)加載了framework和眾多App所需要的通用資源. 然后它開啟一個(gè)Socket接口來監(jiān)聽請求, 根據(jù)請求孵化出新的VM來管理新的App進(jìn)程. 一旦收到新的請求, Zygote會(huì)基于自身預(yù)先加載的VM來孵化出一個(gè)新的VM創(chuàng)建一個(gè)新的進(jìn)程.

啟動(dòng)Zygote之后, init進(jìn)程會(huì)啟動(dòng)runtime進(jìn)程. Zygote會(huì)孵化出一個(gè)超級(jí)管理進(jìn)程---System Server. SystemServer會(huì)啟動(dòng)所有系統(tǒng)核心服務(wù), 例如Activity Manager Service, 硬件相關(guān)的Service等. 到此, 系統(tǒng)準(zhǔn)備好啟動(dòng)它的第一個(gè)App進(jìn)程---Home進(jìn)程了.

2, 啟動(dòng)App流程

用戶點(diǎn)擊Home上的一個(gè)App圖標(biāo), 啟動(dòng)一個(gè)應(yīng)用時(shí):


app launch

Click事件會(huì)調(diào)用startActivity(Intent), 會(huì)通過Binder IPC機(jī)制, 最終調(diào)用到ActivityManagerService. 該Service會(huì)執(zhí)行如下操作:

  • 第一步通過PackageManager的resolveIntent()收集這個(gè)intent對象的指向信息.
  • 指向信息被存儲(chǔ)在一個(gè)intent對象中.
  • 下面重要的一步是通過grantUriPermissionLocked()方法來驗(yàn)證用戶是否有足夠的權(quán)限去調(diào)用該intent對象指向的Activity.
  • 如果有權(quán)限, ActivityManagerService會(huì)檢查并在新的task中啟動(dòng)目標(biāo)activity.
  • 現(xiàn)在, 是時(shí)候檢查這個(gè)進(jìn)程的ProcessRecord是否存在了.

如果ProcessRecord是null, ActivityManagerService會(huì)創(chuàng)建新的進(jìn)程來實(shí)例化目標(biāo)activity.

2.1 創(chuàng)建進(jìn)程

ActivityManagerService調(diào)用startProcessLocked()方法來創(chuàng)建新的進(jìn)程, 該方法會(huì)通過前面講到的socket通道傳遞參數(shù)給Zygote進(jìn)程. Zygote孵化自身, 并調(diào)用ZygoteInit.main()方法來實(shí)例化ActivityThread對象并最終返回新進(jìn)程的pid.

ActivityThread隨后依次調(diào)用Looper.prepareLoop()和Looper.loop()來開啟消息循環(huán).

流程圖如下:


process creation

2.2 綁定Application

接下來要做的就是將進(jìn)程和指定的Application綁定起來. 這個(gè)是通過上節(jié)的ActivityThread對象中調(diào)用bindApplication()方法完成的. 該方法發(fā)送一個(gè)BIND_APPLICATION的消息到消息隊(duì)列中, 最終通過handleBindApplication()方法處理該消息. 然后調(diào)用makeApplication()方法來加載App的classes到內(nèi)存中.

流程如下:


bind application

2.3 啟動(dòng)Activity

經(jīng)過前兩個(gè)步驟之后, 系統(tǒng)已經(jīng)擁有了該application的進(jìn)程. 后面的調(diào)用順序就是普通的從一個(gè)已經(jīng)存在的進(jìn)程中啟動(dòng)一個(gè)新進(jìn)程的activity了.

實(shí)際調(diào)用方法是realStartActivity(), 它會(huì)調(diào)用application線程對象中的sheduleLaunchActivity()發(fā)送一個(gè)LAUNCH_ACTIVITY消息到消息隊(duì)列中, 通過 handleLaunchActivity()來處理該消息.

假設(shè)點(diǎn)擊的是一個(gè)視頻瀏覽的App, 其流程如下:


start activity
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容