關(guān)鍵類說明
整個啟動流程因為會涉及到多次Binder通信,這里先簡要說明一下幾個類的用途量窘,方便大家理解整個交互流程:
- ActivityManagerService :AMS是Android中最核心的服務(wù)之一墙牌,主要負(fù)責(zé)系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作埠况,其職責(zé)與操作系統(tǒng)中的進(jìn)程管理和調(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進(jìn)程的本地方法任内。
- ActivityManagerProxy :AMS服務(wù)在當(dāng)前進(jìn)程的代理類撵渡,負(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)了跨進(jìn)程到System進(jìn)程。
2肋殴、AMS響應(yīng)Launcher進(jìn)程請求
從上面的流程我們知道囤锉,此時AMS應(yīng)該處理Launcher進(jìn)程發(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進(jìn)入Paused狀態(tài)宴凉。至此,AMS對Launcher的請求已經(jīng)響應(yīng)表悬,這是我們發(fā)現(xiàn)又通過Binder通信回調(diào)至Launcher進(jìn)程弥锄。
3、Launcher進(jìn)程掛起Launcher,再次通知AMS
這個流程相對會簡單一些籽暇,我們來看Launcher中的ActivityThread温治,這部分Launcher的ActivityThread處理頁面Paused并且再次通過ActivityManagerProxy通知AMS。
4图仓、AMS創(chuàng)建新的進(jìn)程
創(chuàng)建新進(jìn)程的時候罐盔,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)建一個新的進(jìn)程劫窒,新的進(jìn)程會導(dǎo)入android.app.ActivityThread類本今,并且執(zhí)行它的main函數(shù),這就是每一個應(yīng)用程序都有一個ActivityThread實例來對應(yīng)的原因主巍。
5冠息、應(yīng)用進(jìn)程初始化
我們來看Activity的main函數(shù),這里綁定了主線程的Looper孕索,并進(jìn)入消息循環(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)用進(jìn)程進(jìn)行進(jìn)程間通信的。
6翎嫡、在AMS中注冊應(yīng)用進(jìn)程欠动,啟動啟動棧頂頁面
前面我們提到了AMS負(fù)責(zé)系統(tǒng)中四大組件的啟動、切換钝的、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作翁垂,通過上一個流程我們知道應(yīng)用進(jìn)程創(chuàng)建后通過Binder驅(qū)動與AMS產(chǎn)生交互,此時AMS則將應(yīng)用進(jìn)程創(chuàng)建后的信息進(jìn)行了一次 注冊 硝桩,如果拿Windows系統(tǒng)程序注冊到的注冊表來理解這個過程,可能會更形象一些枚荣。mMainStack.topRunningActivityLocked(null)從堆棧頂端取出要啟動的Activity碗脊,并在realStartActivityLockedhan函數(shù)中通過ApplicationThreadProxy調(diào)回App進(jìn)程啟動頁面。此時在App進(jìn)程,我們可以看到衙伶,經(jīng)過一些列的調(diào)用鏈最終調(diào)用至MainActivity:onCreate函數(shù)祈坠,之后會調(diào)用至onResume,而后會通知AMS該MainActivity已經(jīng)處于resume狀態(tài)矢劲。至此赦拘,整個啟動流程告一段落。
詳細(xì)的啟動流程分析
以被啟動應(yīng)用的角度看整個流程
詳細(xì)分析(個人感覺沒有時序來的容易理解)
補充知識 APP啟動方式
通常來說芬沉,APP中啟動方式分為兩種:冷啟動和熱啟動躺同。
- 冷啟動:當(dāng)啟動應(yīng)用時,后臺沒有該應(yīng)用的進(jìn)程丸逸,這時系統(tǒng)會重新創(chuàng)建一個新的進(jìn)程分配給該應(yīng)用蹋艺,這個啟動方式就是冷啟動。
- 熱啟動:當(dāng)啟動應(yīng)用時黄刚,后臺已有該應(yīng)用的進(jìn)程(例:按back鍵/home鍵捎谨,應(yīng)用雖然會退出,但是該應(yīng)用的進(jìn)程是依然會保留在后臺憔维,可進(jìn)入任務(wù)列表查看)涛救,所以在已有進(jìn)程的情況下,這種啟動會從已有的進(jìn)程中來啟動應(yīng)用业扒,這個方式叫熱啟動检吆。
請注意:上面說的啟動是點擊app的啟動圖標(biāo)來啟動的,而另外一種方式是進(jìn)入最近使用的列表界面來啟動應(yīng)用凶赁,這種不應(yīng)該叫啟動咧栗,應(yīng)該叫恢復(fù)。