It's right time to learn Android's Framework 蝗茁!
前言
- 一個(gè)App是怎么啟動(dòng)起來(lái)的?
- App的程序入口到底是哪里茬故?
- Launcher到底是什么神奇的東西?
- 聽(tīng)說(shuō)還有個(gè)AMS的東西膘盖,它是做什么的?
- Binder是什么?他是如何進(jìn)行IPC通信的?
- Activity生命周期到底是什么時(shí)候調(diào)用的椎组?被誰(shuí)調(diào)用的?
- 等等...
你是不是還有很多類似的疑問(wèn)一直沒(méi)有解決历恐?沒(méi)關(guān)系寸癌,這篇文章將結(jié)合源碼以及大量的優(yōu)秀文章专筷,站在巨人的肩膀上,更加通俗的來(lái)試著解釋一些問(wèn)題蒸苇。但是畢竟源碼繁多磷蛹、經(jīng)驗(yàn)有限,文中不免會(huì)出現(xiàn)一些紕漏甚至是錯(cuò)誤溪烤,還懇請(qǐng)大家指出味咳,互相學(xué)習(xí)。
學(xué)習(xí)目標(biāo)
- 了解從手機(jī)開(kāi)機(jī)第一個(gè)zygote進(jìn)程創(chuàng)建檬嘀,到點(diǎn)擊桌面上的圖標(biāo)槽驶,進(jìn)入一個(gè)App的完整流程,并且從源碼的角度了解到一個(gè)Activity的生命周期是怎么回事
- 了解到ActivityManagerServices(即AMS)枪眉、ActivityStack、ActivityThread再层、Instrumentation等Android framework中非常重要的基礎(chǔ)類的作用贸铜,及相互間的關(guān)系
- 了解AMS與ActivityThread之間利用Binder進(jìn)行IPC通信的過(guò)程,了解AMS和ActivityThread在控制Activity生命周期起到的作用和相互之間的配合
- 了解與Activity相關(guān)的framework層的其他瑣碎問(wèn)題
寫(xiě)作方式
這篇文章我決定采用一問(wèn)一答的方式進(jìn)行聂受。
其實(shí)在這之前蒿秦,我試過(guò)把每個(gè)流程的代碼調(diào)用過(guò)程,用粘貼源代碼的方式寫(xiě)在文章里蛋济,但是寫(xiě)完一部分之后棍鳖,發(fā)現(xiàn)由于代碼量太大,整篇文章和老太太的裹腳布一樣——又臭又長(zhǎng)碗旅,雖然每個(gè)重要的操作可以顯示出詳細(xì)調(diào)用過(guò)程渡处,但是太關(guān)注于細(xì)節(jié)反而導(dǎo)致從整體上不能很好的把握。所以在原來(lái)的基礎(chǔ)之上進(jìn)行了修改祟辟,對(duì)關(guān)鍵的幾個(gè)步驟進(jìn)行重點(diǎn)介紹医瘫,力求語(yǔ)言簡(jiǎn)潔,重點(diǎn)突出旧困,從而讓大家在更高的層次上對(duì)framework層有個(gè)認(rèn)識(shí)醇份,然后結(jié)合后面我給出的參考資料,大家就可以更加快速吼具,更加高效的了解這一塊的整體架構(gòu)僚纷。
主要對(duì)象功能介紹
我們下面的文章將圍繞著這幾個(gè)類進(jìn)行介紹∞趾校可能你第一次看的時(shí)候怖竭,印象不深,不過(guò)沒(méi)關(guān)系陡蝇,當(dāng)你跟隨者我讀完這篇文章的時(shí)候侵状,我會(huì)在最后再次列出這些對(duì)象的功能赞弥,相信那時(shí)候你會(huì)對(duì)這些類更加的熟悉和深刻。
- ActivityManagerServices趣兄,簡(jiǎn)稱AMS绽左,服務(wù)端對(duì)象,負(fù)責(zé)系統(tǒng)中所有Activity的生命周期
- ActivityThread艇潭,App的真正入口拼窥。當(dāng)開(kāi)啟App之后,會(huì)調(diào)用main()開(kāi)始運(yùn)行蹋凝,開(kāi)啟消息循環(huán)隊(duì)列鲁纠,這就是傳說(shuō)中的UI線程或者叫主線程。與ActivityManagerServices配合鳍寂,一起完成Activity的管理工作
- ApplicationThread改含,用來(lái)實(shí)現(xiàn)ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關(guān)Application中的Activity的生命周期時(shí)迄汛,通過(guò)ApplicationThread的代理對(duì)象與ActivityThread通訊捍壤。
- ApplicationThreadProxy,是ApplicationThread在服務(wù)器端的代理鞍爱,負(fù)責(zé)和客戶端的ApplicationThread通訊鹃觉。AMS就是通過(guò)該代理與ActivityThread進(jìn)行通信的。
- Instrumentation睹逃,每一個(gè)應(yīng)用程序只有一個(gè)Instrumentation對(duì)象盗扇,每個(gè)Activity內(nèi)都有一個(gè)對(duì)該對(duì)象的引用。Instrumentation可以理解為應(yīng)用進(jìn)程的管家沉填,ActivityThread要?jiǎng)?chuàng)建或暫停某個(gè)Activity時(shí)疗隶,都需要通過(guò)Instrumentation來(lái)進(jìn)行具體的操作。
- ActivityStack翼闹,Activity在AMS的棧管理抽减,用來(lái)記錄已經(jīng)啟動(dòng)的Activity的先后關(guān)系,狀態(tài)信息等橄碾。通過(guò)ActivityStack決定是否需要啟動(dòng)新的進(jìn)程卵沉。
- ActivityRecord,ActivityStack的管理對(duì)象法牲,每個(gè)Activity在AMS對(duì)應(yīng)一個(gè)ActivityRecord史汗,來(lái)記錄Activity的狀態(tài)以及其他的管理信息。其實(shí)就是服務(wù)器端的Activity對(duì)象的映像拒垃。
- TaskRecord停撞,AMS抽象出來(lái)的一個(gè)“任務(wù)”的概念,是記錄ActivityRecord的棧,一個(gè)“Task”包含若干個(gè)ActivityRecord戈毒。AMS用TaskRecord確保Activity啟動(dòng)和退出的順序艰猬。如果你清楚Activity的4種launchMode,那么對(duì)這個(gè)概念應(yīng)該不陌生埋市。
主要流程介紹
下面將按照App啟動(dòng)過(guò)程的先后順序冠桃,一問(wèn)一答,來(lái)解釋一些事情道宅。
讓我們開(kāi)始吧食听!
zygote是什么?有什么作用污茵?
首先樱报,你覺(jué)得這個(gè)單詞眼熟不?當(dāng)你的程序Crash的時(shí)候泞当,打印的紅色log下面通常帶有這一個(gè)單詞迹蛤。
zygote意為“受精卵“。Android是基于Linux系統(tǒng)的襟士,而在Linux中盗飒,所有的進(jìn)程都是由init進(jìn)程直接或者是間接fork出來(lái)的,zygote進(jìn)程也不例外敌蜂。
在Android系統(tǒng)里面箩兽,zygote是一個(gè)進(jìn)程的名字津肛。Android是基于Linux System的章喉,當(dāng)你的手機(jī)開(kāi)機(jī)的時(shí)候,Linux的內(nèi)核加載完成之后就會(huì)啟動(dòng)一個(gè)叫“init“的進(jìn)程身坐。在Linux System里面秸脱,所有的進(jìn)程都是由init進(jìn)程fork出來(lái)的,我們的zygote進(jìn)程也不例外部蛇。
我們都知道摊唇,每一個(gè)App其實(shí)都是
- 一個(gè)單獨(dú)的dalvik虛擬機(jī)
- 一個(gè)單獨(dú)的進(jìn)程
所以當(dāng)系統(tǒng)里面的第一個(gè)zygote進(jìn)程運(yùn)行之后,在這之后再開(kāi)啟App涯鲁,就相當(dāng)于開(kāi)啟一個(gè)新的進(jìn)程巷查。而為了實(shí)現(xiàn)資源共用和更快的啟動(dòng)速度,Android系統(tǒng)開(kāi)啟新進(jìn)程的方式抹腿,是通過(guò)fork第一個(gè)zygote進(jìn)程實(shí)現(xiàn)的岛请。所以說(shuō),除了第一個(gè)zygote進(jìn)程警绩,其他應(yīng)用所在的進(jìn)程都是zygote的子進(jìn)程崇败,這下你明白為什么這個(gè)進(jìn)程叫“受精卵”了吧?因?yàn)榫拖袷且粋€(gè)受精卵一樣,它能快速的分裂后室,并且產(chǎn)生遺傳物質(zhì)一樣的細(xì)胞缩膝!
SystemServer是什么?有什么作用岸霹?它與zygote的關(guān)系是什么疾层?
首先我要告訴你的是,SystemServer也是一個(gè)進(jìn)程松申,而且是由zygote進(jìn)程fork出來(lái)的云芦。
知道了SystemServer的本質(zhì),我們對(duì)它就不算太陌生了贸桶,這個(gè)進(jìn)程是Android Framework里面兩大非常重要的進(jìn)程之一——另外一個(gè)進(jìn)程就是上面的zygote進(jìn)程舅逸。
為什么說(shuō)SystemServer非常重要呢?因?yàn)橄到y(tǒng)里面重要的服務(wù)都是在這個(gè)進(jìn)程里面開(kāi)啟的皇筛,比如
ActivityManagerService琉历、PackageManagerService、WindowManagerService等等水醋,看著是不是都挺眼熟的旗笔?
那么這些系統(tǒng)服務(wù)是怎么開(kāi)啟起來(lái)的呢?
在zygote開(kāi)啟的時(shí)候拄踪,會(huì)調(diào)用ZygoteInit.main()進(jìn)行初始化
public static void main(String argv[]) {
...ignore some code...
//在加載首個(gè)zygote的時(shí)候蝇恶,會(huì)傳入初始化參數(shù),使得startSystemServer = true
boolean startSystemServer = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...ignore some code...
//開(kāi)始fork我們的SystemServer進(jìn)程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
...ignore some code...
}
我們看下startSystemServer()做了些什么
/**留著這個(gè)注釋惶桐,就是為了說(shuō)明SystemServer確實(shí)是被fork出來(lái)的
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...ignore some code...
//留著這段注釋撮弧,就是為了說(shuō)明上面ZygoteInit.main(String argv[])里面的argv就是通過(guò)這種方式傳遞進(jìn)來(lái)的
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//確實(shí)是fuck出來(lái)的吧,我沒(méi)騙你吧~不對(duì)姚糊,是fork出來(lái)的 -_-|||
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
ActivityManagerService是什么贿衍?什么時(shí)候初始化的?有什么作用救恨?
ActivityManagerService贸辈,簡(jiǎn)稱AMS,服務(wù)端對(duì)象肠槽,負(fù)責(zé)系統(tǒng)中所有Activity的生命周期擎淤。
ActivityManagerService進(jìn)行初始化的時(shí)機(jī)很明確,就是在SystemServer進(jìn)程開(kāi)啟的時(shí)候秸仙,就會(huì)初始化ActivityManagerService嘴拢。從下面的代碼中可以看到
public final class SystemServer {
//zygote的主入口
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
...ignore some code...
//加載本地系統(tǒng)服務(wù)庫(kù),并進(jìn)行初始化
System.loadLibrary("android_servers");
nativeInit();
// 創(chuàng)建系統(tǒng)上下文
createSystemContext();
//初始化SystemServiceManager對(duì)象筋栋,下面的系統(tǒng)服務(wù)開(kāi)啟都需要調(diào)用SystemServiceManager.startService(Class<T>)炊汤,這個(gè)方法通過(guò)反射來(lái)啟動(dòng)對(duì)應(yīng)的服務(wù)
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//開(kāi)啟服務(wù)
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
...ignore some code...
}
//初始化系統(tǒng)上下文對(duì)象mSystemContext,并設(shè)置默認(rèn)的主題,mSystemContext實(shí)際上是一個(gè)ContextImpl對(duì)象。調(diào)用ActivityThread.systemMain()的時(shí)候抢腐,會(huì)調(diào)用ActivityThread.attach(true)姑曙,而在attach()里面,則創(chuàng)建了Application對(duì)象迈倍,并調(diào)用了Application.onCreate()伤靠。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在這里開(kāi)啟了幾個(gè)核心的服務(wù),因?yàn)檫@些服務(wù)之間相互依賴啼染,所以都放在了這個(gè)方法里面宴合。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,因?yàn)槠渌?wù)需要依賴這個(gè)Service迹鹅,因此需要盡快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 現(xiàn)在電源管理已經(jīng)開(kāi)啟卦洽,ActivityManagerService負(fù)責(zé)電源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
經(jīng)過(guò)上面這些步驟,我們的ActivityManagerService對(duì)象已經(jīng)創(chuàng)建好了斜棚,并且完成了成員變量初始化阀蒂。而且在這之前,調(diào)用createSystemContext()創(chuàng)建系統(tǒng)上下文的時(shí)候弟蚀,也已經(jīng)完成了mSystemContext和ActivityThread的創(chuàng)建蚤霞。注意,這是系統(tǒng)進(jìn)程開(kāi)啟時(shí)的流程义钉,在這之后昧绣,會(huì)開(kāi)啟系統(tǒng)的Launcher程序,完成系統(tǒng)界面的加載與顯示捶闸。
你是否會(huì)好奇夜畴,我為什么說(shuō)AMS是服務(wù)端對(duì)象?下面我給你介紹下Android系統(tǒng)里面的服務(wù)器和客戶端的概念鉴嗤。
其實(shí)服務(wù)器客戶端的概念不僅僅存在于Web開(kāi)發(fā)中斩启,在Android的框架設(shè)計(jì)中序调,使用的也是這一種模式醉锅。服務(wù)器端指的就是所有App共用的系統(tǒng)服務(wù),比如我們這里提到的ActivityManagerService发绢,和前面提到的PackageManagerService硬耍、WindowManagerService等等,這些基礎(chǔ)的系統(tǒng)服務(wù)是被所有的App公用的边酒,當(dāng)某個(gè)App想實(shí)現(xiàn)某個(gè)操作的時(shí)候经柴,要告訴這些系統(tǒng)服務(wù),比如你想打開(kāi)一個(gè)App墩朦,那么我們知道了包名和MainActivity類名之后就可以打開(kāi)
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
但是坯认,我們的App通過(guò)調(diào)用startActivity()并不能直接打開(kāi)另外一個(gè)App,這個(gè)方法會(huì)通過(guò)一系列的調(diào)用,最后還是告訴AMS說(shuō):“我要打開(kāi)這個(gè)App牛哺,我知道他的住址和名字陋气,你幫我打開(kāi)吧!”所以是AMS來(lái)通知zygote進(jìn)程來(lái)fork一個(gè)新進(jìn)程引润,來(lái)開(kāi)啟我們的目標(biāo)App的巩趁。這就像是瀏覽器想要打開(kāi)一個(gè)超鏈接一樣,瀏覽器把網(wǎng)頁(yè)地址發(fā)送給服務(wù)器淳附,然后還是服務(wù)器把需要的資源文件發(fā)送給客戶端的议慰。
知道了Android Framework的客戶端服務(wù)器架構(gòu)之后,我們還需要了解一件事情奴曙,那就是我們的App和AMS(SystemServer進(jìn)程)還有zygote進(jìn)程分屬于三個(gè)獨(dú)立的進(jìn)程别凹,他們之間如何通信呢?
App與AMS通過(guò)Binder進(jìn)行IPC通信洽糟,AMS(SystemServer進(jìn)程)與zygote通過(guò)Socket進(jìn)行IPC通信番川。
那么AMS有什么用呢?在前面我們知道了脊框,如果想打開(kāi)一個(gè)App的話颁督,需要AMS去通知zygote進(jìn)程,除此之外浇雹,其實(shí)所有的Activity的開(kāi)啟沉御、暫停、關(guān)閉都需要AMS來(lái)控制昭灵,所以我們說(shuō)吠裆,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。
在Android系統(tǒng)中烂完,任何一個(gè)Activity的啟動(dòng)都是由AMS和應(yīng)用程序進(jìn)程(主要是ActivityThread)相互配合來(lái)完成的试疙。AMS服務(wù)統(tǒng)一調(diào)度系統(tǒng)中所有進(jìn)程的Activity啟動(dòng),而每個(gè)Activity的啟動(dòng)過(guò)程則由其所屬的進(jìn)程具體來(lái)完成抠蚣。
這樣說(shuō)你可能還是覺(jué)得比較抽象祝旷,沒(méi)關(guān)系,下面有一部分是專門(mén)來(lái)介紹AMS與ActivityThread如何一起合作控制Activity的生命周期的嘶窄。
Launcher是什么怀跛?什么時(shí)候啟動(dòng)的?
當(dāng)我們點(diǎn)擊手機(jī)桌面上的圖標(biāo)的時(shí)候柄冲,App就由Launcher開(kāi)始啟動(dòng)了吻谋。但是,你有沒(méi)有思考過(guò)Launcher到底是一個(gè)什么東西现横?
Launcher本質(zhì)上也是一個(gè)應(yīng)用程序漓拾,和我們的App一樣阁最,也是繼承自Activity
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
}
Launcher實(shí)現(xiàn)了點(diǎn)擊、長(zhǎng)按等回調(diào)接口骇两,來(lái)接收用戶的輸入闽撤。既然是普通的App,那么我們的開(kāi)發(fā)經(jīng)驗(yàn)在這里就仍然適用脯颜,比如哟旗,我們點(diǎn)擊圖標(biāo)的時(shí)候,是怎么開(kāi)啟的應(yīng)用呢栋操?如果讓你闸餐,你怎么做這個(gè)功能呢?捕捉圖標(biāo)點(diǎn)擊事件矾芙,然后startActivity()發(fā)送對(duì)應(yīng)的Intent請(qǐng)求唄舍沙!是的,Launcher也是這么做的剔宪,就是這么easy拂铡!
那么到底是處理的哪個(gè)對(duì)象的點(diǎn)擊事件呢?既然Launcher是App葱绒,并且有界面感帅,那么肯定有布局文件呀,是的地淀,我找到了布局文件launcher.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:id="@+id/launcher">
<com.android.launcher2.DragLayer
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<include
android:id="@+id/dock_divider"
layout="@layout/workspace_divider"
android:layout_marginBottom="@dimen/button_bar_height"
android:layout_gravity="bottom" />
<include
android:id="@+id/paged_view_indicator"
layout="@layout/scroll_indicator"
android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/button_bar_height" />
<!-- The workspace contains 5 screens of cells -->
<com.android.launcher2.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/workspace_left_padding"
android:paddingEnd="@dimen/workspace_right_padding"
android:paddingTop="@dimen/workspace_top_padding"
android:paddingBottom="@dimen/workspace_bottom_padding"
launcher:defaultScreen="2"
launcher:cellCountX="@integer/cell_count_x"
launcher:cellCountY="@integer/cell_count_y"
launcher:pageSpacing="@dimen/workspace_page_spacing"
launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
<include android:id="@+id/cell1" layout="@layout/workspace_screen" />
<include android:id="@+id/cell2" layout="@layout/workspace_screen" />
<include android:id="@+id/cell3" layout="@layout/workspace_screen" />
<include android:id="@+id/cell4" layout="@layout/workspace_screen" />
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher2.Workspace>
...ignore some code...
</com.android.launcher2.DragLayer>
</FrameLayout>
為了方便查看失球,我刪除了很多代碼,從上面這些我們應(yīng)該可以看出一些東西來(lái):Launcher大量使用<include/>標(biāo)簽來(lái)實(shí)現(xiàn)界面的復(fù)用帮毁,而且定義了很多的自定義控件實(shí)現(xiàn)界面效果实苞,dock_divider從布局的參數(shù)聲明上可以猜出,是底部操作欄和上面圖標(biāo)布局的分割線烈疚,而paged_view_indicator則是頁(yè)面指示器黔牵,和App首次進(jìn)入的引導(dǎo)頁(yè)下面的界面引導(dǎo)是一樣的道理。當(dāng)然爷肝,我們最關(guān)心的是Workspace這個(gè)布局猾浦,因?yàn)樽⑨尷锩嬲f(shuō)在這里面包含了5個(gè)屏幕的單元格,想必你也猜到了阶剑,這個(gè)就是在首頁(yè)存放我們圖標(biāo)的那五個(gè)界面(不同的ROM會(huì)做不同的DIY跃巡,數(shù)量不固定)危号。
接下來(lái)牧愁,我們應(yīng)該打開(kāi)workspace_screen布局,看看里面有什么東東外莲。
workspace_screen.xml
<com.android.launcher2.CellLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/cell_layout_left_padding"
android:paddingEnd="@dimen/cell_layout_right_padding"
android:paddingTop="@dimen/cell_layout_top_padding"
android:paddingBottom="@dimen/cell_layout_bottom_padding"
android:hapticFeedbackEnabled="false"
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
launcher:widthGap="@dimen/workspace_width_gap"
launcher:heightGap="@dimen/workspace_height_gap"
launcher:maxGap="@dimen/workspace_max_gap" />
里面就一個(gè)CellLayout猪半,也是一個(gè)自定義布局兔朦,那么我們就可以猜到了,既然可以存放圖標(biāo)磨确,那么這個(gè)自定義的布局很有可能是繼承自ViewGroup或者是其子類沽甥,實(shí)際上,CellLayout確實(shí)是繼承自ViewGroup乏奥。在CellLayout里面摆舟,只放了一個(gè)子View,那就是ShortcutAndWidgetContainer邓了。從名字也可以看出來(lái)恨诱,ShortcutAndWidgetContainer這個(gè)類就是用來(lái)存放快捷圖標(biāo)和Widget小部件的,那么里面放的是什么對(duì)象呢骗炉?
在桌面上的圖標(biāo)照宝,使用的是BubbleTextView對(duì)象,這個(gè)對(duì)象在TextView的基礎(chǔ)之上句葵,添加了一些特效厕鹃,比如你長(zhǎng)按移動(dòng)圖標(biāo)的時(shí)候,圖標(biāo)位置會(huì)出現(xiàn)一個(gè)背景(不同版本的效果不同)乍丈,所以我們找到BubbleTextView對(duì)象的點(diǎn)擊事件剂碴,就可以找到Launcher如何開(kāi)啟一個(gè)App了。
除了在桌面上有圖標(biāo)之外轻专,在程序列表中點(diǎn)擊圖標(biāo)汗茄,也可以開(kāi)啟對(duì)應(yīng)的程序。這里的圖標(biāo)使用的不是BubbleTextView對(duì)象铭若,而是PagedViewIcon對(duì)象洪碳,我們?nèi)绻业剿狞c(diǎn)擊事件,就也可以找到Launcher如何開(kāi)啟一個(gè)App叼屠。
其實(shí)說(shuō)這么多瞳腌,和今天的主題隔著十萬(wàn)八千里,上面這些東西镜雨,你有興趣就看嫂侍,沒(méi)興趣就直接跳過(guò),不知道不影響這篇文章閱讀荚坞。
BubbleTextView的點(diǎn)擊事件在哪里呢挑宠?我來(lái)告訴你:在Launcher.onClick(View v)里面。
/**
* Launches the intent referred by the clicked shortcut
*/
public void onClick(View v) {
...ignore some code...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
//開(kāi)始開(kāi)啟Activity咯~
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//如果點(diǎn)擊的是圖標(biāo)文件夾颓影,就打開(kāi)文件夾
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
從上面的代碼我們可以看到各淀,在桌面上點(diǎn)擊快捷圖標(biāo)的時(shí)候,會(huì)調(diào)用
startActivitySafely(v, intent, tag);
那么從程序列表界面诡挂,點(diǎn)擊圖標(biāo)的時(shí)候會(huì)發(fā)生什么呢碎浇?實(shí)際上临谱,程序列表界面使用的是AppsCustomizePagedView對(duì)象,所以我在這個(gè)類里面找到了onClick(View v)奴璃。
com.android.launcher2.AppsCustomizePagedView.java
/**
* The Apps/Customize page that displays all the applications, widgets, and shortcuts.
*/
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
View.OnClickListener, View.OnKeyListener, DragSource,
PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
LauncherTransitionable {
@Override
public void onClick(View v) {
...ignore some code...
if (v instanceof PagedViewIcon) {
mLauncher.updateWallpaperVisibility(true);
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
} else if (v instanceof PagedViewWidget) {
...ignore some code..
}
}
}
可以看到悉默,調(diào)用的是
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
和上面一樣摊趾!這叫什么夕晓?這叫殊途同歸!
所以咱們現(xiàn)在又明白了一件事情:不管從哪里點(diǎn)擊圖標(biāo)喊衫,調(diào)用的都是Launcher.startActivitySafely()雳旅。
- 下面我們就可以一步步的來(lái)看一下Launcher.startActivitySafely()到底做了什么事情剖膳。
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
}
return success;
}
調(diào)用了startActivity(v, intent, tag)
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent, opts.toBundle());
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
} else {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent);
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(), null);
}
}
return true;
} catch (SecurityException e) {
...
}
return false;
}
這里會(huì)調(diào)用Activity.startActivity(intent, opts.toBundle()),這個(gè)方法熟悉嗎岭辣?這就是我們經(jīng)常用到的Activity.startActivity(Intent)的重載函數(shù)吱晒。而且由于設(shè)置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以這個(gè)Activity會(huì)添加到一個(gè)新的Task棧中,而且沦童,startActivity()調(diào)用的其實(shí)是startActivityForResult()這個(gè)方法仑濒。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
所以我們現(xiàn)在明確了,Launcher中開(kāi)啟一個(gè)App偷遗,其實(shí)和我們?cè)贏ctivity中直接startActivity()基本一樣墩瞳,都是調(diào)用了Activity.startActivityForResult()。
Instrumentation是什么氏豌?和ActivityThread是什么關(guān)系喉酌?
還記得前面說(shuō)過(guò)的Instrumentation對(duì)象嗎?每個(gè)Activity都持有Instrumentation對(duì)象的一個(gè)引用泵喘,但是整個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象泪电。當(dāng)startActivityForResult()調(diào)用之后,實(shí)際上還是調(diào)用了mInstrumentation.execStartActivity()
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...ignore some code...
} else {
if (options != null) {
//當(dāng)現(xiàn)在的Activity有父Activity的時(shí)候會(huì)調(diào)用纪铺,但是在startActivityFromChild()內(nèi)部實(shí)際還是調(diào)用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()的實(shí)現(xiàn)
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...ignore some code...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
所以當(dāng)我們?cè)诔绦蛑姓{(diào)用startActivity()的 時(shí)候相速,實(shí)際上調(diào)用的是Instrumentation的相關(guān)的方法。
Instrumentation意為“儀器”鲜锚,我們先看一下這個(gè)類里面包含哪些方法吧
我們可以看到突诬,這個(gè)類里面的方法大多數(shù)和Application和Activity有關(guān),是的芜繁,這個(gè)類就是完成對(duì)Application和Activity初始化和生命周期的工具類旺隙。比如說(shuō),我單獨(dú)挑一個(gè)callActivityOnCreate()讓你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對(duì)activity.performCreate(icicle);這一行代碼熟悉嗎骏令?這一行里面就調(diào)用了傳說(shuō)中的Activity的入口函數(shù)onCreate()蔬捷,不信?接著往下看
Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒(méi)騙你吧伏社,onCreate在這里調(diào)用了吧抠刺。但是有一件事情必須說(shuō)清楚塔淤,那就是這個(gè)Instrumentation類這么重要摘昌,為啥我在開(kāi)發(fā)的過(guò)程中速妖,沒(méi)有發(fā)現(xiàn)他的蹤跡呢?
是的聪黎,Instrumentation這個(gè)類很重要罕容,對(duì)Activity生命周期方法的調(diào)用根本就離不開(kāi)他,他可以說(shuō)是一個(gè)大管家稿饰,但是锦秒,這個(gè)大管家比較害羞,是一個(gè)女的喉镰,管內(nèi)不管外旅择,是老板娘~
那么你可能要問(wèn)了,老板是誰(shuí)呀侣姆?
老板當(dāng)然是大名鼎鼎的ActivityThread了生真!
ActivityThread你都沒(méi)聽(tīng)說(shuō)過(guò)?那你肯定聽(tīng)說(shuō)過(guò)傳說(shuō)中的UI線程吧捺宗?是的柱蟀,這就是UI線程。我們前面說(shuō)過(guò)蚜厉,App和AMS是通過(guò)Binder傳遞信息的长已,那么ActivityThread就是專門(mén)與AMS的外交工作的。
AMS說(shuō):“ActivityThread昼牛,你給我暫停一個(gè)Activity术瓮!”
ActivityThread就說(shuō):“沒(méi)問(wèn)題!”然后轉(zhuǎn)身和Instrumentation說(shuō):“老婆贰健,AMS讓暫停一個(gè)Activity斤斧,我這里忙著呢,你快去幫我把這事辦了把~”
于是霎烙,Instrumentation就去把事兒搞定了撬讽。
所以說(shuō),AMS是董事會(huì)悬垃,負(fù)責(zé)指揮和調(diào)度的游昼,ActivityThread是老板,雖然說(shuō)家里的事自己說(shuō)了算尝蠕,但是需要聽(tīng)從AMS的指揮烘豌,而Instrumentation則是老板娘,負(fù)責(zé)家里的大事小事看彼,但是一般不拋頭露面廊佩,聽(tīng)一家之主ActivityThread的安排囚聚。
如何理解AMS和ActivityThread之間的Binder通信?
前面我們說(shuō)到标锄,在調(diào)用startActivity()的時(shí)候顽铸,實(shí)際上調(diào)用的是
mInstrumentation.execStartActivity()
但是到這里還沒(méi)完呢!里面又調(diào)用了下面的方法
ActivityManagerNative.getDefault()
.startActivity
這里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠(yuǎn)程接口料皇,即ActivityManagerProxy谓松。
怎么知道的呢?往下看
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
//從類聲明上践剂,我們可以看到ActivityManagerNative是Binder的一個(gè)子類鬼譬,而且實(shí)現(xiàn)了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通過(guò)單例模式獲取一個(gè)IActivityManager對(duì)象,這個(gè)對(duì)象通過(guò)asInterface(b)獲得
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
//最終返回的還是一個(gè)ActivityManagerProxy對(duì)象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//這里面的Binder類型的obj參數(shù)會(huì)作為ActivityManagerProxy的成員變量保存為mRemote成員變量逊脯,負(fù)責(zé)進(jìn)行IPC通信
return new ActivityManagerProxy(obj);
}
}
再看ActivityManagerProxy.startActivity()优质,在這里面做的事情就是IPC通信,利用Binder對(duì)象军洼,調(diào)用transact()巩螃,把所有需要的參數(shù)封裝成Parcel對(duì)象,向AMS發(fā)送數(shù)據(jù)進(jìn)行通信歉眷。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
Binder本質(zhì)上只是一種底層通信方式牺六,和具體服務(wù)沒(méi)有關(guān)系。為了提供具體服務(wù)汗捡,Server必須提供一套接口函數(shù)以便Client通過(guò)遠(yuǎn)程訪問(wèn)使用各種服務(wù)淑际。這時(shí)通常采用Proxy設(shè)計(jì)模式:將接口函數(shù)定義在一個(gè)抽象類中,Server和Client都會(huì)以該抽象類為基類實(shí)現(xiàn)所有接口函數(shù)扇住,所不同的是Server端是真正的功能實(shí)現(xiàn)春缕,而Client端是對(duì)這些函數(shù)遠(yuǎn)程調(diào)用請(qǐng)求的包裝。
為了更方便的說(shuō)明客戶端和服務(wù)器之間的Binder通信艘蹋,下面以ActivityManagerServices和他在客戶端的代理類ActivityManagerProxy為例锄贼。
ActivityManagerServices和ActivityManagerProxy都實(shí)現(xiàn)了同一個(gè)接口——IActivityManager。
class ActivityManagerProxy implements IActivityManager{}
public final class ActivityManagerService extends ActivityManagerNative{}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
雖然都實(shí)現(xiàn)了同一個(gè)接口女阀,但是代理對(duì)象ActivityManagerProxy并不會(huì)對(duì)這些方法進(jìn)行真正地實(shí)現(xiàn)宅荤,ActivityManagerProxy只是通過(guò)這種方式對(duì)方法的參數(shù)進(jìn)行打包(因?yàn)槎紝?shí)現(xiàn)了相同接口,所以可以保證同一個(gè)方法有相同的參數(shù)浸策,即對(duì)要傳輸給服務(wù)器的數(shù)據(jù)進(jìn)行打包)冯键,真正實(shí)現(xiàn)的是ActivityManagerService。
但是這個(gè)地方并不是直接由客戶端傳遞給服務(wù)器庸汗,而是通過(guò)Binder驅(qū)動(dòng)進(jìn)行中轉(zhuǎn)惫确。其實(shí)我對(duì)Binder驅(qū)動(dòng)并不熟悉,我們就把他當(dāng)做一個(gè)中轉(zhuǎn)站就OK,客戶端調(diào)用ActivityManagerProxy接口里面的方法改化,把數(shù)據(jù)傳送給Binder驅(qū)動(dòng)掩蛤,然后Binder驅(qū)動(dòng)就會(huì)把這些東西轉(zhuǎn)發(fā)給服務(wù)器的ActivityManagerServices,由ActivityManagerServices去真正的實(shí)施具體的操作陈肛。
但是Binder只能傳遞數(shù)據(jù)揍鸟,并不知道是要調(diào)用ActivityManagerServices的哪個(gè)方法,所以在數(shù)據(jù)中會(huì)添加方法的唯一標(biāo)識(shí)碼燥爷,比如前面的startActivity()方法:
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
...ignore some code...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
上面的START_ACTIVITY_TRANSACTION就是方法標(biāo)示蜈亩,data是要傳輸給Binder驅(qū)動(dòng)的數(shù)據(jù)懦窘,reply則接受操作的返回值前翎。
即
客戶端:ActivityManagerProxy =====>Binder驅(qū)動(dòng)=====> ActivityManagerService:服務(wù)器
而且由于繼承了同樣的公共接口類,ActivityManagerProxy提供了與ActivityManagerService一樣的函數(shù)原型畅涂,使用戶感覺(jué)不出Server是運(yùn)行在本地還是遠(yuǎn)端港华,從而可以更加方便的調(diào)用這些重要的系統(tǒng)服務(wù)。
但是午衰!這里Binder通信是單方向的立宜,即從ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情臊岸,應(yīng)該咋辦呢橙数?
還是通過(guò)Binder通信,不過(guò)是換了另外一對(duì)帅戒,換成了ApplicationThread和ApplicationThreadProxy灯帮。
客戶端:ApplicationThread <=====Binder驅(qū)動(dòng)<===== ApplicationThreadProxy:服務(wù)器
他們也都實(shí)現(xiàn)了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}
剩下的就不必多說(shuō)了吧,和前面一樣逻住。
AMS接收到客戶端的請(qǐng)求之后钟哥,會(huì)如何開(kāi)啟一個(gè)Activity?
OK瞎访,至此腻贰,點(diǎn)擊桌面圖標(biāo)調(diào)用startActivity(),終于把數(shù)據(jù)和要開(kāi)啟Activity的請(qǐng)求發(fā)送到了AMS了扒秸。說(shuō)了這么多播演,其實(shí)這些都在一瞬間完成了,下面咱們研究下AMS到底做了什么伴奥。
注:前方有高能的方法調(diào)用鏈写烤,如果你現(xiàn)在累了,請(qǐng)先喝杯咖啡或者是上趟廁所休息下
AMS收到startActivity的請(qǐng)求之后渔伯,會(huì)按照如下的方法鏈進(jìn)行調(diào)用
調(diào)用startActivity()
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
調(diào)用startActivityAsUser()
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
...ignore some code...
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
在這里又出現(xiàn)了一個(gè)新對(duì)象ActivityStackSupervisor顶霞,通過(guò)這個(gè)類可以實(shí)現(xiàn)對(duì)ActivityStack的部分操作。
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
...ignore some code...
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options,
componentSpecified, null, container, inTask);
...ignore some code...
}
繼續(xù)調(diào)用startActivityLocked()
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
TaskRecord inTask) {
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
if (err < 0) {
notifyActivityDrawnForKeyguard();
}
return err;
}
調(diào)用startActivityUncheckedLocked(),此時(shí)要啟動(dòng)的Activity已經(jīng)通過(guò)檢驗(yàn),被認(rèn)為是一個(gè)正當(dāng)?shù)膯?dòng)請(qǐng)求选浑。
終于蓝厌,在這里調(diào)用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。
ActivityRecord代表的就是要開(kāi)啟的Activity對(duì)象古徒,里面分裝了很多信息拓提,比如所在的ActivityTask等,如果這是首次打開(kāi)應(yīng)用隧膘,那么這個(gè)Activity會(huì)被放到ActivityTask的棧頂代态,
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
...ignore some code...
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
...ignore some code...
return ActivityManager.START_SUCCESS;
}
調(diào)用的是ActivityStack.startActivityLocked()
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//ActivityRecord中存儲(chǔ)的TaskRecord信息
TaskRecord rTask = r.task;
...ignore some code...
//如果不是在新的ActivityTask(也就是TaskRecord)中的話,就找出要運(yùn)行在的TaskRecord對(duì)象
TaskRecord task = null;
if (!newTask) {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// task中的所有Activity都結(jié)束了
continue;
}
if (task == r.task) {
// 找到了
if (!startIt) {
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
...ignore some code...
// Place a new activity at top of stack, so it is next to interact
// with the user.
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
...ignore some code...
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
靠疹吃!這來(lái)回折騰什么呢蹦疑!從ActivityStackSupervisor到ActivityStack,又調(diào)回ActivityStackSupervisor萨驶,這到底是在折騰什么玩意扒复荨!G晃亍叁温!
淡定...淡定...我知道你也在心里罵娘,世界如此美妙核畴,你卻如此暴躁膝但,這樣不好,不好...
來(lái)來(lái)來(lái)谤草,咱們繼續(xù)哈跟束,剛才說(shuō)到哪里了?哦咖刃,對(duì)泳炉,咱們一起看下StackSupervisor.resumeTopActivitiesLocked(this, r, options)
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
...ignore some code...
return result;
}
我...已無(wú)力吐槽了,又調(diào)回ActivityStack去了...
ActivityStack.resumeTopActivityLocked()
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}
咱們堅(jiān)持住嚎杨,看一下ActivityStack.resumeTopActivityInnerLocked()到底進(jìn)行了什么操作
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
...ignore some code...
//找出還沒(méi)結(jié)束的首個(gè)ActivityRecord
ActivityRecord next = topRunningActivityLocked(null);
//如果一個(gè)沒(méi)結(jié)束的Activity都沒(méi)有花鹅,就開(kāi)啟Launcher程序
if (next == null) {
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}
//先需要暫停當(dāng)前的Activity。因?yàn)槲覀兪窃贚ancher中啟動(dòng)mainActivity枫浙,所以當(dāng)前mResumedActivity刨肃!=null,調(diào)用startPausingLocked()使得Launcher進(jìn)入Pausing狀態(tài)
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
}
在這個(gè)方法里箩帚,prev.app為記錄啟動(dòng)Lancher進(jìn)程的ProcessRecord真友,prev.app.thread為L(zhǎng)ancher進(jìn)程的遠(yuǎn)程調(diào)用接口IApplicationThead,所以可以調(diào)用prev.app.thread.schedulePauseActivity紧帕,到Lancher進(jìn)程暫停指定Activity盔然。
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
boolean dontWait) {
if (mPausingActivity != null) {
completePauseLocked(false);
}
...ignore some code...
if (prev.app != null && prev.app.thread != null)
try {
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...ignore some code...
}
在Lancher進(jìn)程中消息傳遞桅打,調(diào)用ActivityThread.handlePauseActivity(),最終調(diào)用ActivityThread.performPauseActivity()暫停指定Activity愈案。接著通過(guò)前面所說(shuō)的Binder通信挺尾,通知AMS已經(jīng)完成暫停的操作。
ActivityManagerNative.getDefault().activityPaused(token).
上面這些調(diào)用過(guò)程非常復(fù)雜站绪,源碼中各種條件判斷讓人眼花繚亂遭铺,所以說(shuō)如果你沒(méi)記住也沒(méi)關(guān)系,你只要記住這個(gè)流程恢准,理解了Android在控制Activity生命周期時(shí)是如何操作魂挂,以及是通過(guò)哪幾個(gè)關(guān)鍵的類進(jìn)行操作的就可以了,以后遇到相關(guān)的問(wèn)題之道從哪塊下手即可馁筐,這些過(guò)程我雖然也是擼了一遍涂召,但還是記不清。
最后來(lái)一張高清無(wú)碼大圖眯漩,方便大家記憶:
請(qǐng)戳這里(圖片3.3M芹扭,請(qǐng)用電腦觀看)
送給你們的彩蛋
不要使用 startActivityForResult(intent,RESULT_OK)
這是因?yàn)閟tartActivity()是這樣實(shí)現(xiàn)的
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
而
public static final int RESULT_OK = -1;
所以
startActivityForResult(intent,RESULT_OK) = startActivity()
你不可能從onActivityResult()里面收到任何回調(diào)麻顶。而這個(gè)問(wèn)題是相當(dāng)難以被發(fā)現(xiàn)的赦抖,就是因?yàn)檫@個(gè)坑,我工作一年多來(lái)第一次加班到9點(diǎn) (ˇ?ˇ)
一個(gè)App的程序入口到底是什么辅肾?
是ActivityThread.main()队萤。
整個(gè)App的主線程的消息循環(huán)是在哪里創(chuàng)建的?
是在ActivityThread初始化的時(shí)候矫钓,就已經(jīng)創(chuàng)建消息循環(huán)了要尔,所以在主線程里面創(chuàng)建Handler不需要指定Looper,而如果在其他線程使用Handler新娜,則需要單獨(dú)使用Looper.prepare()和Looper.loop()創(chuàng)建消息循環(huán)赵辕。
public static void main(String[] args) {
...ignore some code...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
...ignore some code...
}
Application是在什么時(shí)候創(chuàng)建的?onCreate()什么時(shí)候調(diào)用的概龄?
也是在ActivityThread.main()的時(shí)候还惠,再具體點(diǎn)呢,就是在thread.attach(false)的時(shí)候私杜。
看你的表情蚕键,不信是吧!凱子哥帶你溜溜~
我們先看一下ActivityThread.attach()
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
//普通App進(jìn)這里
if (!system) {
...ignore some code...
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {
//這個(gè)分支在SystemServer加載的時(shí)候會(huì)進(jìn)入衰粹,通過(guò)調(diào)用
// private void createSystemContext() {
// ActivityThread activityThread = ActivityThread.systemMain()锣光;
//}
// public static ActivityThread systemMain() {
// if (!ActivityManager.isHighEndGfx()) {
// HardwareRenderer.disable(true);
// } else {
// HardwareRenderer.enableForegroundTrimming();
// }
// ActivityThread thread = new ActivityThread();
// thread.attach(true);
// return thread;
// }
}
}
這里需要關(guān)注的就是mgr.attachApplication(mAppThread),這個(gè)就會(huì)通過(guò)Binder調(diào)用到AMS里面對(duì)應(yīng)的方法
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
然后就是
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
}
thread是IApplicationThread铝耻,實(shí)際上就是ApplicationThread在服務(wù)端的代理類ApplicationThreadProxy誊爹,然后又通過(guò)IPC就會(huì)調(diào)用到ApplicationThread的對(duì)應(yīng)方法
private class ApplicationThread extends ApplicationThreadNative {
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
...ignore some code...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
}
我們需要關(guān)注的其實(shí)就是最后的sendMessage(),里面有函數(shù)的編號(hào)H.BIND_APPLICATION,然后這個(gè)Messge會(huì)被H這個(gè)Handler處理
private class H extends Handler {
...ignore some code...
public static final int BIND_APPLICATION = 110;
...ignore some code...
public void handleMessage(Message msg) {
switch (msg.what) {
...ignore some code...
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...ignore some code...
}
}
最后就在下面這個(gè)方法中频丘,完成了實(shí)例化箍铭,撥那個(gè)企鵝通過(guò)mInstrumentation.callApplicationOnCreate實(shí)現(xiàn)了onCreate()的調(diào)用。
private void handleBindApplication(AppBindData data) {
try {
...ignore some code...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...ignore some code...
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) { }
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
data.info是一個(gè)LoadeApk對(duì)象椎镣。
LoadeApk.data.info.makeApplication()
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) { }
mActivityThread.mAllApplications.add(app);
mApplication = app;
//傳進(jìn)來(lái)的是null诈火,所以這里不會(huì)執(zhí)行,onCreate在上一層執(zhí)行
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
}
...ignore some code...
}
return app;
}
所以最后還是通過(guò)Instrumentation.makeApplication()實(shí)例化的状答,這個(gè)老板娘真的很厲害呀冷守!
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
而且通過(guò)反射拿到Application對(duì)象之后,直接調(diào)用attach()惊科,所以attach()調(diào)用是在onCreate()之前的拍摇。
參考文章
下面的這些文章都是這方面比較精品的,希望你抽出時(shí)間研究馆截,這可能需要花費(fèi)很長(zhǎng)時(shí)間充活,但是如果你想進(jìn)階為中高級(jí)開(kāi)發(fā)者,這一步是必須的蜡娶。
再次感謝下面這些文章的作者的分享精神混卵。
Binder
zygote
ActivityThread、Instrumentation窖张、AMS
- Android Activity.startActivity流程簡(jiǎn)介
- Android應(yīng)用程序進(jìn)程啟動(dòng)過(guò)程的源代碼分析
- 框架層理解Activity生命周期(APP啟動(dòng)過(guò)程)
- Android應(yīng)用程序窗口設(shè)計(jì)框架介紹
- ActivityManagerService分析一:AMS的啟動(dòng)
- Android應(yīng)用程序窗口設(shè)計(jì)框架介紹
Launcher
結(jié)語(yǔ)
OK幕随,到這里,這篇文章算是告一段落了宿接,我們?cè)倩仡^看看一開(kāi)始的幾個(gè)問(wèn)題赘淮,你還困惑嗎?
- 一個(gè)App是怎么啟動(dòng)起來(lái)的睦霎?
- App的程序入口到底是哪里梢卸?
- Launcher到底是什么神奇的東西?
- 聽(tīng)說(shuō)還有個(gè)AMS的東西副女,它是做什么的蛤高?
- Binder是什么?他是如何進(jìn)行IPC通信的肮塞?
- Activity生命周期到底是什么時(shí)候調(diào)用的襟齿?被誰(shuí)調(diào)用的?
再回過(guò)頭來(lái)看看這些類枕赵,你還迷惑嗎猜欺?
- ActivityManagerServices,簡(jiǎn)稱AMS拷窜,服務(wù)端對(duì)象开皿,負(fù)責(zé)系統(tǒng)中所有Activity的生命周期
- ActivityThread涧黄,App的真正入口。當(dāng)開(kāi)啟App之后赋荆,會(huì)調(diào)用main()開(kāi)始運(yùn)行笋妥,開(kāi)啟消息循環(huán)隊(duì)列,這就是傳說(shuō)中的UI線程或者叫主線程窄潭。與ActivityManagerServices配合春宣,一起完成Activity的管理工作
- ApplicationThread,用來(lái)實(shí)現(xiàn)ActivityManagerService與ActivityThread之間的交互嫉你。在ActivityManagerService需要管理相關(guān)Application中的Activity的生命周期時(shí)月帝,通過(guò)ApplicationThread的代理對(duì)象與ActivityThread通訊。
- ApplicationThreadProxy幽污,是ApplicationThread在服務(wù)器端的代理嚷辅,負(fù)責(zé)和客戶端的ApplicationThread通訊。AMS就是通過(guò)該代理與ActivityThread進(jìn)行通信的距误。
- Instrumentation簸搞,每一個(gè)應(yīng)用程序只有一個(gè)Instrumentation對(duì)象,每個(gè)Activity內(nèi)都有一個(gè)對(duì)該對(duì)象的引用准潭。Instrumentation可以理解為應(yīng)用進(jìn)程的管家趁俊,ActivityThread要?jiǎng)?chuàng)建或暫停某個(gè)Activity時(shí),都需要通過(guò)Instrumentation來(lái)進(jìn)行具體的操作惋鹅。
- ActivityStack则酝,Activity在AMS的棧管理,用來(lái)記錄已經(jīng)啟動(dòng)的Activity的先后關(guān)系闰集,狀態(tài)信息等。通過(guò)ActivityStack決定是否需要啟動(dòng)新的進(jìn)程般卑。
- ActivityRecord武鲁,ActivityStack的管理對(duì)象,每個(gè)Activity在AMS對(duì)應(yīng)一個(gè)ActivityRecord蝠检,來(lái)記錄Activity的狀態(tài)以及其他的管理信息沐鼠。其實(shí)就是服務(wù)器端的Activity對(duì)象的映像。
- TaskRecord叹谁,AMS抽象出來(lái)的一個(gè)“任務(wù)”的概念饲梭,是記錄ActivityRecord的棧,一個(gè)“Task”包含若干個(gè)ActivityRecord焰檩。AMS用TaskRecord確保Activity啟動(dòng)和退出的順序憔涉。如果你清楚Activity的4種launchMode,那么對(duì)這個(gè)概念應(yīng)該不陌生析苫。
如果你還感到迷惑的話兜叨,就把這篇文章多讀幾遍吧穿扳,信息量可能比較多,需要慢慢消化~
尊重原創(chuàng)国旷,轉(zhuǎn)載請(qǐng)注明:From 凱子哥(http://blog.csdn.net/zhaokaiqiang1992) 侵權(quán)必究矛物!
關(guān)注我的微博,可以獲得更多精彩內(nèi)容
<a target="_blank"><img border="0" src="http://service.t.sina.com.cn/widget/qmd/1783932377/a0641c19/10.png"/></a>