Android App 啟動原理

Android App 啟動原理

說白了,App 啟動原理就是在講一件事:

你點了桌面圖標之后,App 到底是怎么一步步跑起來并把頁面顯示出來的。

這里面會出現(xiàn)幾個關鍵角色:

Launcher(桌面 App)

AMS(ActivityManagerService)

Zygote

應用進程創(chuàng)建

ActivityThread

Application

目標Activity

先記住這條主線就夠了:

點圖標 -> Launcher 發(fā)起啟動 -> AMS 校驗+調(diào)度 -> Zygote fork 進程 -> 應用進程起來 -> 創(chuàng)建 Application -> 啟動 Activity -> 頁面顯示

先搞清楚什么叫“App 啟動”

平時說啟動,一般分 3 種:

冷啟動:進程沒了,需要新建進程

熱啟動:進程還在,只是把界面切回前臺

溫啟動:進程在,但Activity要重建

面試最愛問的是冷啟動,因為它把系統(tǒng)關鍵鏈路都串起來了。

點圖標后,第一步是誰在處理

你點圖標時,先響應的是Launcher(桌面程序)。

Launcher 本質(zhì)也是普通 Android 應用,只是它負責桌面和應用入口。

它會拿到目標 App 的Intent,然后發(fā)起startActivity()請求。

但這時候還不會直接進目標 App,而是先交給系統(tǒng)服務處理。

簡單說就是:

Launcher 不負責創(chuàng)建目標進程

真正做啟動調(diào)度的是系統(tǒng)服務

這個核心服務就是AMS

AMS 在這個過程里干什么

AMS(ActivityManagerService)是 Android 里負責組件調(diào)度、進程管理的核心系統(tǒng)服務。

收到 Launcher 請求后,它主要做這幾件事:

檢查目標Activity能不能啟動

看目標 App 進程在不在

不在就先創(chuàng)建進程

進程好了再通知應用啟動目標Activity

所以可以把 AMS 理解成“總調(diào)度”:

它不畫頁面,但它決定誰先做、什么時候做、在哪個進程做。

進程不存在時,怎么創(chuàng)建

這一步是冷啟動最核心的地方。

Android 不會讓 App 自己亂建進程,而是統(tǒng)一交給Zygote來孵化。

4.1 Zygote 是什么

Zygote可以理解成“應用進程母體”。

它提前做了很多通用初始化,比如:

啟動虛擬機

加載系統(tǒng)類

預加載常用資源

這樣后面創(chuàng)建應用進程會更快,而且fork還能復用父進程資源,省內(nèi)存。

4.2 AMS 怎么讓 Zygote 創(chuàng)建進程

AMS 發(fā)現(xiàn)目標 App 還沒進程,就會給Zygote發(fā)請求。

然后Zygote通過fork()拉起一個新的應用進程。

新進程起來后,會有自己獨立的:

進程空間

虛擬機環(huán)境

主線程

到這一步,App 就不是“靜態(tài)安裝包”了,而是一個真正跑起來的 Linux 進程。

新進程起來后,誰接管主線程

進程創(chuàng)建完,不是馬上就能看到頁面。

它先會進入應用自己的入口,也就是ActivityThread。

很多人看名字會誤會,以為它只是個線程類。其實它更像:

應用主線程這邊的總管。

它會負責一堆關鍵事:

建主線程消息循環(huán)

跟 AMS 通信

創(chuàng)建Application

創(chuàng)建并啟動Activity

一句話理解:

AMS 管系統(tǒng)側(cè)調(diào)度,ActivityThread管應用側(cè)執(zhí)行。

6.Application什么時候創(chuàng)建

在目標Activity真正啟動前,系統(tǒng)會先把Application創(chuàng)建出來。

常見流程大概是:

創(chuàng)建LoadedApk等運行信息

創(chuàng)建應用Context

反射創(chuàng)建Application實例

回調(diào)Application#onCreate()

所以我們才會把全局初始化放在Application#onCreate(),比如:

日志框架

路由

網(wǎng)絡庫

崩潰監(jiān)控

但這里有個重點:

Application#onCreate()越重,冷啟動通常越慢。

因為這一步?jīng)]結束,首頁一般還沒真正展示出來。

7.Activity是怎么啟動的

應用進程準備好后,AMS 會通知應用去啟動目標Activity。

應用側(cè)的ActivityThread收到消息后,會走一套啟動流程,大概包括:

創(chuàng)建Activity實例

創(chuàng)建Context

綁定PhoneWindow

調(diào)用Activity#attach()

觸發(fā)生命周期回調(diào)

常見啟動順序是:

onCreate()

onStart()

onResume()

一般在onCreate()里會做:

setContentView()

初始化 View

初始化數(shù)據(jù)

綁定監(jiān)聽

等界面測量、布局、繪制都完成,用戶才會真正看到頁面。

從源碼角度記啟動鏈路

你可以把主鏈路記成下面這 9 步:

Launcher 發(fā)起startActivity()

請求進入系統(tǒng)進程里的AMS

AMS 判斷目標進程在不在

不在就讓Zygotefork 新進程

新進程進入ActivityThread.main()

創(chuàng)建Application

ActivityThread收到啟動Activity消息

創(chuàng)建并回調(diào)目標Activity

頁面繪制完成,啟動結束

不要求你死背每個源碼細節(jié),但這 4 件事一定要清楚:

誰發(fā)起

誰調(diào)度

誰創(chuàng)建進程

誰在應用側(cè)執(zhí)行生命周期

為什么冷啟動會慢

根本原因就一句話:冷啟動要做的事太多,而且很多都堆在主線程前期。

常見耗時點有:

創(chuàng)建進程本身要時間

Application#onCreate()干太多事

首頁Activity#onCreate()邏輯太重

首屏布局太深,繪制慢

同步 I/O、數(shù)據(jù)庫、網(wǎng)絡阻塞主線程

初始化 SDK 太多

所以很多時候慢的不是框架流程本身,而是業(yè)務初始化太“重”。

啟動優(yōu)化一般在優(yōu)化什么

核心目標就兩個:

首屏更早可見,主線程更少被卡。

常見做法:

非核心組件延遲初始化

按優(yōu)先級拆初始化任務

耗時任務盡量異步

降低首頁布局復雜度

避免主線程 I/O

用啟動任務編排框架統(tǒng)一管理順序

比如:

埋點、統(tǒng)計、更新檢查可以延后

不影響首屏的 SDK 放子線程

首屏只加載必須數(shù)據(jù)

面試里怎么講更順

如果面試官讓你簡單講 App 啟動,可以這么說:

App 啟動從 Launcher 點圖標開始,Launcher 把請求交給 AMS。AMS 負責統(tǒng)一調(diào)度:先判斷目標進程是否存在,不存在就讓 Zygote fork 新進程。新進程起來后進入ActivityThread,先創(chuàng)建Application,再創(chuàng)建并啟動目標Activity,最后頁面繪制完成,用戶看到首頁。

如果對方繼續(xù)追問,你可以往這幾個點展開:

冷啟動、熱啟動、溫啟動區(qū)別

Zygote為什么能加速啟動

Application和Activity的先后順序

啟動優(yōu)化主要優(yōu)化哪些耗時點

一張簡化流程圖

整條鏈路可以記成:

Launcher -> AMS -> Zygote -> App Process -> ActivityThread -> Application -> Activity -> View 顯示

一句話收尾

App 啟動的核心就是:系統(tǒng)先決定要不要建進程,再由應用進程完成Application和Activity創(chuàng)建,最后把頁面繪制出來。

只記 3 個關鍵詞也行:

AMS:負責調(diào)度

Zygote:負責建進程

ActivityThread:負責應用側(cè)執(zhí)行啟動流程

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

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

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