Android應(yīng)用啟動流程分析

關(guān)鍵類說明

整個啟動流程因為會涉及到多次Binder通信,這里先簡要說明一下幾個類的用途,方便大家理解整個交互流程:

  • ActivityManagerService :AMS是Android中最核心的服務(wù)之一,主要負(fù)責(zé)系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用進程的管理和調(diào)度等工作,其職責(zé)與操作系統(tǒng)中的進程管理和調(diào)度模塊相類似,因此它在Android中非常重要,它本身也是一個Binder的實現(xiàn)類。
  • Instrumentation :顧名思義,它用來監(jiān)控應(yīng)用程序和系統(tǒng)的交互。
  • ActivityThread :應(yīng)用的入口類,系統(tǒng)通過調(diào)用main函數(shù),開啟消息循環(huán)隊列。ActivityThread所在線程被稱為應(yīng)用的主線程(UI線程)。
  • ApplicationThread :ApplicationThread提供Binder通訊接口,AMS則通過代理調(diào)用此App進程的本地方法。
  • ActivityManagerProxy :AMS服務(wù)在當(dāng)前進程的代理類,負(fù)責(zé)與AMS通信。
  • ApplicationThreadProxy :ApplicationThread在AMS服務(wù)中的代理類,負(fù)責(zé)與ApplicationThread通信。

流程分析

1、Launcher響應(yīng)用戶點擊,通知AMS

Launcher做為應(yīng)用的入口,通過starActicity輾轉(zhuǎn)調(diào)用到Activity:startActivityForResult而后則調(diào)用至Instrumentation:execStartActivity。在Instrumentation:execStartActivity方法中,這里的 ActivityManagerNative.getDefault 返回ActivityManagerService的遠(yuǎn)程接口,即 ActivityManagerProxy 接口,通過Binder驅(qū)動程序, ActivityManagerProxy 與AMS服務(wù)通信,則實現(xiàn)了跨進程到System進程。

2、AMS響應(yīng)Launcher進程請求

從上面的流程我們知道,此時AMS應(yīng)該處理Launcher進程發(fā)來的請求,請參看時序圖及源碼,此時我們調(diào)用到ActivityStackSupervisor:startActivityUncheckedLocked方法。在這個方法中函數(shù)經(jīng)過intent的標(biāo)志值設(shè)置,通過findTaskLocked函數(shù)來查找存不存這樣的Task,這里返回的結(jié)果是null,即intentActivity為null,因此,需要創(chuàng)建一個新的Task來啟動這個Activity。現(xiàn)在處理堆棧頂端的Activity是Launcher,與我們即將要啟動的MainActivity不是同一個Activity,創(chuàng)建了一個新的Task里面來啟動這個Activity。經(jīng)過棧頂檢測,則需要將Launcher推入Paused狀態(tài),才可以啟動新的Activity。后續(xù)則調(diào)用至ActivityStack:startPausingLocked,在這個函數(shù)中的prev.app.thread是一個ApplicationThread對象的遠(yuǎn)程接口,通過調(diào)用這個遠(yuǎn)程接口的schedulePauseActivity來通知Launcher進入Paused狀態(tài)。至此,AMS對Launcher的請求已經(jīng)響應(yīng),這是我們發(fā)現(xiàn)又通過Binder通信回調(diào)至Launcher進程。

3、Launcher進程掛起Launcher,再次通知AMS

這個流程相對會簡單一些,我們來看Launcher中的ActivityThread,這部分Launcher的ActivityThread處理頁面Paused并且再次通過ActivityManagerProxy通知AMS。

4、AMS創(chuàng)建新的進程

創(chuàng)建新進程的時候,AMS會保存一個ProcessRecord信息,如果應(yīng)用程序中的AndroidManifest.xml配置文件中,我們沒有指定Application標(biāo)簽的process屬性,系統(tǒng)就會默認(rèn)使用package的名稱。每一個應(yīng)用程序都有自己的uid,因此,這里uid + process的組合就可以為每一個應(yīng)用程序創(chuàng)建一個ProcessRecord。這里主要是調(diào)用Process:start接口來創(chuàng)建一個新的進程,新的進程會導(dǎo)入android.app.ActivityThread類,并且執(zhí)行它的main函數(shù),這就是每一個應(yīng)用程序都有一個ActivityThread實例來對應(yīng)的原因。

5、應(yīng)用進程初始化

我們來看Activity的main函數(shù),這里綁定了主線程的Looper,并進入消息循環(huán),大家應(yīng)該知道,整個Android系統(tǒng)是消息驅(qū)動的,這也是為什么主線程默認(rèn)綁定Looper的原因。attach函數(shù)最終調(diào)用了ActivityManagerService的遠(yuǎn)程接口ActivityManagerProxy的attachApplication函數(shù),傳入的參數(shù)是mAppThread,這是一個ApplicationThread類型的Binder對象,它的作用是AMS與應(yīng)用進程進行進程間通信的。

6、在AMS中注冊應(yīng)用進程,啟動啟動棧頂頁面

前面我們提到了AMS負(fù)責(zé)系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用進程的管理和調(diào)度等工作,通過上一個流程我們知道應(yīng)用進程創(chuàng)建后通過Binder驅(qū)動與AMS產(chǎn)生交互,此時AMS則將應(yīng)用進程創(chuàng)建后的信息進行了一次 注冊 ,如果拿Windows系統(tǒng)程序注冊到的注冊表來理解這個過程,可能會更形象一些。mMainStack.topRunningActivityLocked(null)從堆棧頂端取出要啟動的Activity,并在realStartActivityLockedhan函數(shù)中通過ApplicationThreadProxy調(diào)回App進程啟動頁面。此時在App進程,我們可以看到,經(jīng)過一些列的調(diào)用鏈最終調(diào)用至MainActivity:onCreate函數(shù),之后會調(diào)用至onResume,而后會通知AMS該MainActivity已經(jīng)處于resume狀態(tài)。至此,整個啟動流程告一段落。

應(yīng)用啟動流程時序圖.png

詳細(xì)的啟動流程分析

以被啟動應(yīng)用的角度看整個流程

詳細(xì)分析(個人感覺沒有時序來的容易理解)

以應(yīng)用啟動的角度看整個過程.jpg

補充知識 APP啟動方式

通常來說,APP中啟動方式分為兩種:冷啟動和熱啟動。
  • 冷啟動:當(dāng)啟動應(yīng)用時,后臺沒有該應(yīng)用的進程,這時系統(tǒng)會重新創(chuàng)建一個新的進程分配給該應(yīng)用,這個啟動方式就是冷啟動。
  • 熱啟動:當(dāng)啟動應(yīng)用時,后臺已有該應(yīng)用的進程(例:按back鍵/home鍵,應(yīng)用雖然會退出,但是該應(yīng)用的進程是依然會保留在后臺,可進入任務(wù)列表查看),所以在已有進程的情況下,這種啟動會從已有的進程中來啟動應(yīng)用,這個方式叫熱啟動。

請注意:上面說的啟動是點擊app的啟動圖標(biāo)來啟動的,而另外一種方式是進入最近使用的列表界面來啟動應(yīng)用,這種不應(yīng)該叫啟動,應(yīng)該叫恢復(fù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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