It's right time to learn Android's Framework !
前言
- 一個App是怎么啟動起來的?
- App的程序入口到底是哪里?
- Launcher到底是什么神奇的東西?
- 聽說還有個AMS的東西,它是做什么的?
- Binder是什么?他是如何進行IPC通信的?
- Activity生命周期到底是什么時候調(diào)用的?被誰調(diào)用的?
- 等等...
你是不是還有很多類似的疑問一直沒有解決?沒關系,這篇文章將結合源碼以及大量的優(yōu)秀文章,站在巨人的肩膀上,更加通俗的來試著解釋一些問題。但是畢竟源碼繁多、經(jīng)驗有限,文中不免會出現(xiàn)一些紕漏甚至是錯誤,還懇請大家指出,互相學習。
學習目標
- 了解從手機開機第一個zygote進程創(chuàng)建,到點擊桌面上的圖標,進入一個App的完整流程,并且從源碼的角度了解到一個Activity的生命周期是怎么回事
- 了解到ActivityManagerServices(即AMS)、ActivityStack、ActivityThread、Instrumentation等Android framework中非常重要的基礎類的作用,及相互間的關系
- 了解AMS與ActivityThread之間利用Binder進行IPC通信的過程,了解AMS和ActivityThread在控制Activity生命周期起到的作用和相互之間的配合
- 了解與Activity相關的framework層的其他瑣碎問題
寫作方式
這篇文章我決定采用一問一答的方式進行。
其實在這之前,我試過把每個流程的代碼調(diào)用過程,用粘貼源代碼的方式寫在文章里,但是寫完一部分之后,發(fā)現(xiàn)由于代碼量太大,整篇文章和老太太的裹腳布一樣——又臭又長,雖然每個重要的操作可以顯示出詳細調(diào)用過程,但是太關注于細節(jié)反而導致從整體上不能很好的把握。所以在原來的基礎之上進行了修改,對關鍵的幾個步驟進行重點介紹,力求語言簡潔,重點突出,從而讓大家在更高的層次上對framework層有個認識,然后結合后面我給出的參考資料,大家就可以更加快速,更加高效的了解這一塊的整體架構。
主要對象功能介紹
我們下面的文章將圍繞著這幾個類進行介紹。可能你第一次看的時候,印象不深,不過沒關系,當你跟隨者我讀完這篇文章的時候,我會在最后再次列出這些對象的功能,相信那時候你會對這些類更加的熟悉和深刻。
- ActivityManagerServices,簡稱AMS,服務端對象,負責系統(tǒng)中所有Activity的生命周期
- ActivityThread,App的真正入口。當開啟App之后,會調(diào)用main()開始運行,開啟消息循環(huán)隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一起完成Activity的管理工作
- ApplicationThread,用來實現(xiàn)ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關Application中的Activity的生命周期時,通過ApplicationThread的代理對象與ActivityThread通訊。
- ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的。
- Instrumentation,每一個應用程序只有一個Instrumentation對象,每個Activity內(nèi)都有一個對該對象的引用。Instrumentation可以理解為應用進程的管家,ActivityThread要創(chuàng)建或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作。
- ActivityStack,Activity在AMS的棧管理,用來記錄已經(jīng)啟動的Activity的先后關系,狀態(tài)信息等。通過ActivityStack決定是否需要啟動新的進程。
- ActivityRecord,ActivityStack的管理對象,每個Activity在AMS對應一個ActivityRecord,來記錄Activity的狀態(tài)以及其他的管理信息。其實就是服務器端的Activity對象的映像。
- TaskRecord,AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord。AMS用TaskRecord確保Activity啟動和退出的順序。如果你清楚Activity的4種launchMode,那么對這個概念應該不陌生。
主要流程介紹
下面將按照App啟動過程的先后順序,一問一答,來解釋一些事情。
讓我們開始吧!
zygote是什么?有什么作用?
首先,你覺得這個單詞眼熟不?當你的程序Crash的時候,打印的紅色log下面通常帶有這一個單詞。
zygote意為“受精卵“。Android是基于Linux系統(tǒng)的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。
在Android系統(tǒng)里面,zygote是一個進程的名字。Android是基于Linux System的,當你的手機開機的時候,Linux的內(nèi)核加載完成之后就會啟動一個叫“init“的進程。在Linux System里面,所有的進程都是由init進程fork出來的,我們的zygote進程也不例外。
我們都知道,每一個App其實都是
- 一個單獨的dalvik虛擬機
- 一個單獨的進程
所以當系統(tǒng)里面的第一個zygote進程運行之后,在這之后再開啟App,就相當于開啟一個新的進程。而為了實現(xiàn)資源共用和更快的啟動速度,Android系統(tǒng)開啟新進程的方式,是通過fork第一個zygote進程實現(xiàn)的。所以說,除了第一個zygote進程,其他應用所在的進程都是zygote的子進程,這下你明白為什么這個進程叫“受精卵”了吧?因為就像是一個受精卵一樣,它能快速的分裂,并且產(chǎn)生遺傳物質(zhì)一樣的細胞!
SystemServer是什么?有什么作用?它與zygote的關系是什么?
首先我要告訴你的是,SystemServer也是一個進程,而且是由zygote進程fork出來的。
知道了SystemServer的本質(zhì),我們對它就不算太陌生了,這個進程是Android Framework里面兩大非常重要的進程之一——另外一個進程就是上面的zygote進程。
為什么說SystemServer非常重要呢?因為系統(tǒng)里面重要的服務都是在這個進程里面開啟的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看著是不是都挺眼熟的?
那么這些系統(tǒng)服務是怎么開啟起來的呢?
在zygote開啟的時候,會調(diào)用ZygoteInit.main()進行初始化
public static void main(String argv[]) {
...ignore some code...
//在加載首個zygote的時候,會傳入初始化參數(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...
//開始fork我們的SystemServer進程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
...ignore some code...
}
我們看下startSystemServer()做了些什么
/**留著這個注釋,就是為了說明SystemServer確實是被fork出來的
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...ignore some code...
//留著這段注釋,就是為了說明上面ZygoteInit.main(String argv[])里面的argv就是通過這種方式傳遞進來的
/* 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);
//確實是fuck出來的吧,我沒騙你吧~不對,是fork出來的 -_-|||
/* 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是什么?什么時候初始化的?有什么作用?
ActivityManagerService,簡稱AMS,服務端對象,負責系統(tǒng)中所有Activity的生命周期。
ActivityManagerService進行初始化的時機很明確,就是在SystemServer進程開啟的時候,就會初始化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)服務庫,并進行初始化
System.loadLibrary("android_servers");
nativeInit();
// 創(chuàng)建系統(tǒng)上下文
createSystemContext();
//初始化SystemServiceManager對象,下面的系統(tǒng)服務開啟都需要調(diào)用SystemServiceManager.startService(Class<T>),這個方法通過反射來啟動對應的服務
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//開啟服務
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)上下文對象mSystemContext,并設置默認的主題,mSystemContext實際上是一個ContextImpl對象。調(diào)用ActivityThread.systemMain()的時候,會調(diào)用ActivityThread.attach(true),而在attach()里面,則創(chuàng)建了Application對象,并調(diào)用了Application.onCreate()。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在這里開啟了幾個核心的服務,因為這些服務之間相互依賴,所以都放在了這個方法里面。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,因為其他服務需要依賴這個Service,因此需要盡快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 現(xiàn)在電源管理已經(jīng)開啟,ActivityManagerService負責電源管理功能
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)過上面這些步驟,我們的ActivityManagerService對象已經(jīng)創(chuàng)建好了,并且完成了成員變量初始化。而且在這之前,調(diào)用createSystemContext()創(chuàng)建系統(tǒng)上下文的時候,也已經(jīng)完成了mSystemContext和ActivityThread的創(chuàng)建。注意,這是系統(tǒng)進程開啟時的流程,在這之后,會開啟系統(tǒng)的Launcher程序,完成系統(tǒng)界面的加載與顯示。
你是否會好奇,我為什么說AMS是服務端對象?下面我給你介紹下Android系統(tǒng)里面的服務器和客戶端的概念。
其實服務器客戶端的概念不僅僅存在于Web開發(fā)中,在Android的框架設計中,使用的也是這一種模式。服務器端指的就是所有App共用的系統(tǒng)服務,比如我們這里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎的系統(tǒng)服務是被所有的App公用的,當某個App想實現(xiàn)某個操作的時候,要告訴這些系統(tǒng)服務,比如你想打開一個App,那么我們知道了包名和MainActivity類名之后就可以打開
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
但是,我們的App通過調(diào)用startActivity()并不能直接打開另外一個App,這個方法會通過一系列的調(diào)用,最后還是告訴AMS說:“我要打開這個App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進程來fork一個新進程,來開啟我們的目標App的。這就像是瀏覽器想要打開一個超鏈接一樣,瀏覽器把網(wǎng)頁地址發(fā)送給服務器,然后還是服務器把需要的資源文件發(fā)送給客戶端的。
知道了Android Framework的客戶端服務器架構之后,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬于三個獨立的進程,他們之間如何通信呢?
App與AMS通過Binder進行IPC通信,AMS(SystemServer進程)與zygote通過Socket進行IPC通信。
那么AMS有什么用呢?在前面我們知道了,如果想打開一個App的話,需要AMS去通知zygote進程,除此之外,其實所有的Activity的開啟、暫停、關閉都需要AMS來控制,所以我們說,AMS負責系統(tǒng)中所有Activity的生命周期。
在Android系統(tǒng)中,任何一個Activity的啟動都是由AMS和應用程序進程(主要是ActivityThread)相互配合來完成的。AMS服務統(tǒng)一調(diào)度系統(tǒng)中所有進程的Activity啟動,而每個Activity的啟動過程則由其所屬的進程具體來完成。
這樣說你可能還是覺得比較抽象,沒關系,下面有一部分是專門來介紹AMS與ActivityThread如何一起合作控制Activity的生命周期的。
Launcher是什么?什么時候啟動的?
當我們點擊手機桌面上的圖標的時候,App就由Launcher開始啟動了。但是,你有沒有思考過Launcher到底是一個什么東西?
Launcher本質(zhì)上也是一個應用程序,和我們的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實現(xiàn)了點擊、長按等回調(diào)接口,來接收用戶的輸入。既然是普通的App,那么我們的開發(fā)經(jīng)驗在這里就仍然適用,比如,我們點擊圖標的時候,是怎么開啟的應用呢?如果讓你,你怎么做這個功能呢?捕捉圖標點擊事件,然后startActivity()發(fā)送對應的Intent請求唄!是的,Launcher也是這么做的,就是這么easy!
那么到底是處理的哪個對象的點擊事件呢?既然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>
為了方便查看,我刪除了很多代碼,從上面這些我們應該可以看出一些東西來:Launcher大量使用<include/>標簽來實現(xiàn)界面的復用,而且定義了很多的自定義控件實現(xiàn)界面效果,dock_divider從布局的參數(shù)聲明上可以猜出,是底部操作欄和上面圖標布局的分割線,而paged_view_indicator則是頁面指示器,和App首次進入的引導頁下面的界面引導是一樣的道理。當然,我們最關心的是Workspace這個布局,因為注釋里面說在這里面包含了5個屏幕的單元格,想必你也猜到了,這個就是在首頁存放我們圖標的那五個界面(不同的ROM會做不同的DIY,數(shù)量不固定)。
接下來,我們應該打開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" />
里面就一個CellLayout,也是一個自定義布局,那么我們就可以猜到了,既然可以存放圖標,那么這個自定義的布局很有可能是繼承自ViewGroup或者是其子類,實際上,CellLayout確實是繼承自ViewGroup。在CellLayout里面,只放了一個子View,那就是ShortcutAndWidgetContainer。從名字也可以看出來,ShortcutAndWidgetContainer這個類就是用來存放快捷圖標和Widget小部件的,那么里面放的是什么對象呢?
在桌面上的圖標,使用的是BubbleTextView對象,這個對象在TextView的基礎之上,添加了一些特效,比如你長按移動圖標的時候,圖標位置會出現(xiàn)一個背景(不同版本的效果不同),所以我們找到BubbleTextView對象的點擊事件,就可以找到Launcher如何開啟一個App了。
除了在桌面上有圖標之外,在程序列表中點擊圖標,也可以開啟對應的程序。這里的圖標使用的不是BubbleTextView對象,而是PagedViewIcon對象,我們?nèi)绻业剿狞c擊事件,就也可以找到Launcher如何開啟一個App。
其實說這么多,和今天的主題隔著十萬八千里,上面這些東西,你有興趣就看,沒興趣就直接跳過,不知道不影響這篇文章閱讀。
BubbleTextView的點擊事件在哪里呢?我來告訴你:在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()));
//開始開啟Activity咯~
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//如果點擊的是圖標文件夾,就打開文件夾
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
從上面的代碼我們可以看到,在桌面上點擊快捷圖標的時候,會調(diào)用
startActivitySafely(v, intent, tag);
那么從程序列表界面,點擊圖標的時候會發(fā)生什么呢?實際上,程序列表界面使用的是AppsCustomizePagedView對象,所以我在這個類里面找到了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ào)用的都是Launcher.startActivitySafely()。
- 下面我們就可以一步步的來看一下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;
}
這里會調(diào)用Activity.startActivity(intent, opts.toBundle()),這個方法熟悉嗎?這就是我們經(jīng)常用到的Activity.startActivity(Intent)的重載函數(shù)。而且由于設置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以這個Activity會添加到一個新的Task棧中,而且,startActivity()調(diào)用的其實是startActivityForResult()這個方法。
@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中開啟一個App,其實和我們在Activity中直接startActivity()基本一樣,都是調(diào)用了Activity.startActivityForResult()。
Instrumentation是什么?和ActivityThread是什么關系?
還記得前面說過的Instrumentation對象嗎?每個Activity都持有Instrumentation對象的一個引用,但是整個進程只會存在一個Instrumentation對象。當startActivityForResult()調(diào)用之后,實際上還是調(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) {
//當現(xiàn)在的Activity有父Activity的時候會調(diào)用,但是在startActivityFromChild()內(nèi)部實際還是調(diào)用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()的實現(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;
}
所以當我們在程序中調(diào)用startActivity()的 時候,實際上調(diào)用的是Instrumentation的相關的方法。
Instrumentation意為“儀器”,我們先看一下這個類里面包含哪些方法吧

我們可以看到,這個類里面的方法大多數(shù)和Application和Activity有關,是的,這個類就是完成對Application和Activity初始化和生命周期的工具類。比如說,我單獨挑一個callActivityOnCreate()讓你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對activity.performCreate(icicle);這一行代碼熟悉嗎?這一行里面就調(diào)用了傳說中的Activity的入口函數(shù)onCreate(),不信?接著往下看
Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒騙你吧,onCreate在這里調(diào)用了吧。但是有一件事情必須說清楚,那就是這個Instrumentation類這么重要,為啥我在開發(fā)的過程中,沒有發(fā)現(xiàn)他的蹤跡呢?
是的,Instrumentation這個類很重要,對Activity生命周期方法的調(diào)用根本就離不開他,他可以說是一個大管家,但是,這個大管家比較害羞,是一個女的,管內(nèi)不管外,是老板娘~
那么你可能要問了,老板是誰呀?
老板當然是大名鼎鼎的ActivityThread了!
ActivityThread你都沒聽說過?那你肯定聽說過傳說中的UI線程吧?是的,這就是UI線程。我們前面說過,App和AMS是通過Binder傳遞信息的,那么ActivityThread就是專門與AMS的外交工作的。
AMS說:“ActivityThread,你給我暫停一個Activity!”
ActivityThread就說:“沒問題!”然后轉(zhuǎn)身和Instrumentation說:“老婆,AMS讓暫停一個Activity,我這里忙著呢,你快去幫我把這事辦了把~”
于是,Instrumentation就去把事兒搞定了。
所以說,AMS是董事會,負責指揮和調(diào)度的,ActivityThread是老板,雖然說家里的事自己說了算,但是需要聽從AMS的指揮,而Instrumentation則是老板娘,負責家里的大事小事,但是一般不拋頭露面,聽一家之主ActivityThread的安排。
如何理解AMS和ActivityThread之間的Binder通信?
前面我們說到,在調(diào)用startActivity()的時候,實際上調(diào)用的是
mInstrumentation.execStartActivity()
但是到這里還沒完呢!里面又調(diào)用了下面的方法
ActivityManagerNative.getDefault()
.startActivity
這里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠程接口,即ActivityManagerProxy。
怎么知道的呢?往下看
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
//從類聲明上,我們可以看到ActivityManagerNative是Binder的一個子類,而且實現(xiàn)了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通過單例模式獲取一個IActivityManager對象,這個對象通過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;
}
};
}
//最終返回的還是一個ActivityManagerProxy對象
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ù)會作為ActivityManagerProxy的成員變量保存為mRemote成員變量,負責進行IPC通信
return new ActivityManagerProxy(obj);
}
}
再看ActivityManagerProxy.startActivity(),在這里面做的事情就是IPC通信,利用Binder對象,調(diào)用transact(),把所有需要的參數(shù)封裝成Parcel對象,向AMS發(fā)送數(shù)據(jù)進行通信。
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ì)上只是一種底層通信方式,和具體服務沒有關系。為了提供具體服務,Server必須提供一套接口函數(shù)以便Client通過遠程訪問使用各種服務。這時通常采用Proxy設計模式:將接口函數(shù)定義在一個抽象類中,Server和Client都會以該抽象類為基類實現(xiàn)所有接口函數(shù),所不同的是Server端是真正的功能實現(xiàn),而Client端是對這些函數(shù)遠程調(diào)用請求的包裝。
為了更方便的說明客戶端和服務器之間的Binder通信,下面以ActivityManagerServices和他在客戶端的代理類ActivityManagerProxy為例。
ActivityManagerServices和ActivityManagerProxy都實現(xiàn)了同一個接口——IActivityManager。
class ActivityManagerProxy implements IActivityManager{}
public final class ActivityManagerService extends ActivityManagerNative{}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
雖然都實現(xiàn)了同一個接口,但是代理對象ActivityManagerProxy并不會對這些方法進行真正地實現(xiàn),ActivityManagerProxy只是通過這種方式對方法的參數(shù)進行打包(因為都實現(xiàn)了相同接口,所以可以保證同一個方法有相同的參數(shù),即對要傳輸給服務器的數(shù)據(jù)進行打包),真正實現(xiàn)的是ActivityManagerService。
但是這個地方并不是直接由客戶端傳遞給服務器,而是通過Binder驅(qū)動進行中轉(zhuǎn)。其實我對Binder驅(qū)動并不熟悉,我們就把他當做一個中轉(zhuǎn)站就OK,客戶端調(diào)用ActivityManagerProxy接口里面的方法,把數(shù)據(jù)傳送給Binder驅(qū)動,然后Binder驅(qū)動就會把這些東西轉(zhuǎn)發(fā)給服務器的ActivityManagerServices,由ActivityManagerServices去真正的實施具體的操作。
但是Binder只能傳遞數(shù)據(jù),并不知道是要調(diào)用ActivityManagerServices的哪個方法,所以在數(shù)據(jù)中會添加方法的唯一標識碼,比如前面的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就是方法標示,data是要傳輸給Binder驅(qū)動的數(shù)據(jù),reply則接受操作的返回值。
即
客戶端:ActivityManagerProxy =====>Binder驅(qū)動=====> ActivityManagerService:服務器
而且由于繼承了同樣的公共接口類,ActivityManagerProxy提供了與ActivityManagerService一樣的函數(shù)原型,使用戶感覺不出Server是運行在本地還是遠端,從而可以更加方便的調(diào)用這些重要的系統(tǒng)服務。
但是!這里Binder通信是單方向的,即從ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,應該咋辦呢?
還是通過Binder通信,不過是換了另外一對,換成了ApplicationThread和ApplicationThreadProxy。
客戶端:ApplicationThread <=====Binder驅(qū)動<===== ApplicationThreadProxy:服務器
他們也都實現(xiàn)了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}
剩下的就不必多說了吧,和前面一樣。
AMS接收到客戶端的請求之后,會如何開啟一個Activity?
OK,至此,點擊桌面圖標調(diào)用startActivity(),終于把數(shù)據(jù)和要開啟Activity的請求發(fā)送到了AMS了。說了這么多,其實這些都在一瞬間完成了,下面咱們研究下AMS到底做了什么。
注:前方有高能的方法調(diào)用鏈,如果你現(xiàn)在累了,請先喝杯咖啡或者是上趟廁所休息下
AMS收到startActivity的請求之后,會按照如下的方法鏈進行調(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)了一個新對象ActivityStackSupervisor,通過這個類可以實現(xiàn)對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(),此時要啟動的Activity已經(jīng)通過檢驗,被認為是一個正當?shù)膯诱埱蟆?/p>
終于,在這里調(diào)用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。
ActivityRecord代表的就是要開啟的Activity對象,里面分裝了很多信息,比如所在的ActivityTask等,如果這是首次打開應用,那么這個Activity會被放到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中存儲的TaskRecord信息
TaskRecord rTask = r.task;
...ignore some code...
//如果不是在新的ActivityTask(也就是TaskRecord)中的話,就找出要運行在的TaskRecord對象
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都結束了
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);
}
}
靠!這來回折騰什么呢!從ActivityStackSupervisor到ActivityStack,又調(diào)回ActivityStackSupervisor,這到底是在折騰什么玩意啊!!!
淡定...淡定...我知道你也在心里罵娘,世界如此美妙,你卻如此暴躁,這樣不好,不好...
來來來,咱們繼續(xù)哈,剛才說到哪里了?哦,對,咱們一起看下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;
}
我...已無力吐槽了,又調(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;
}
咱們堅持住,看一下ActivityStack.resumeTopActivityInnerLocked()到底進行了什么操作
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
...ignore some code...
//找出還沒結束的首個ActivityRecord
ActivityRecord next = topRunningActivityLocked(null);
//如果一個沒結束的Activity都沒有,就開啟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);
}
//先需要暫停當前的Activity。因為我們是在Lancher中啟動mainActivity,所以當前mResumedActivity!=null,調(diào)用startPausingLocked()使得Launcher進入Pausing狀態(tài)
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
}
在這個方法里,prev.app為記錄啟動Lancher進程的ProcessRecord,prev.app.thread為Lancher進程的遠程調(diào)用接口IApplicationThead,所以可以調(diào)用prev.app.thread.schedulePauseActivity,到Lancher進程暫停指定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進程中消息傳遞,調(diào)用ActivityThread.handlePauseActivity(),最終調(diào)用ActivityThread.performPauseActivity()暫停指定Activity。接著通過前面所說的Binder通信,通知AMS已經(jīng)完成暫停的操作。
ActivityManagerNative.getDefault().activityPaused(token).
上面這些調(diào)用過程非常復雜,源碼中各種條件判斷讓人眼花繚亂,所以說如果你沒記住也沒關系,你只要記住這個流程,理解了Android在控制Activity生命周期時是如何操作,以及是通過哪幾個關鍵的類進行操作的就可以了,以后遇到相關的問題之道從哪塊下手即可,這些過程我雖然也是擼了一遍,但還是記不清。
最后來一張高清無碼大圖,方便大家記憶:
送給你們的彩蛋
不要使用 startActivityForResult(intent,RESULT_OK)
這是因為startActivity()是這樣實現(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)。而這個問題是相當難以被發(fā)現(xiàn)的,就是因為這個坑,我工作一年多來第一次加班到9點 (ˇ?ˇ)
一個App的程序入口到底是什么?
是ActivityThread.main()。
整個App的主線程的消息循環(huán)是在哪里創(chuàng)建的?
是在ActivityThread初始化的時候,就已經(jīng)創(chuàng)建消息循環(huán)了,所以在主線程里面創(chuàng)建Handler不需要指定Looper,而如果在其他線程使用Handler,則需要單獨使用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是在什么時候創(chuàng)建的?onCreate()什么時候調(diào)用的?
也是在ActivityThread.main()的時候,再具體點呢,就是在thread.attach(false)的時候。
看你的表情,不信是吧!凱子哥帶你溜溜~
我們先看一下ActivityThread.attach()
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
//普通App進這里
if (!system) {
...ignore some code...
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {
//這個分支在SystemServer加載的時候會進入,通過調(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;
// }
}
}
這里需要關注的就是mgr.attachApplication(mAppThread),這個就會通過Binder調(diào)用到AMS里面對應的方法
@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,實際上就是ApplicationThread在服務端的代理類ApplicationThreadProxy,然后又通過IPC就會調(diào)用到ApplicationThread的對應方法
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);
}
}
我們需要關注的其實就是最后的sendMessage(),里面有函數(shù)的編號H.BIND_APPLICATION,然后這個Messge會被H這個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...
}
}
最后就在下面這個方法中,完成了實例化,撥那個企鵝通過mInstrumentation.callApplicationOnCreate實現(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是一個LoadeApk對象。
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;
//傳進來的是null,所以這里不會執(zhí)行,onCreate在上一層執(zhí)行
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
}
...ignore some code...
}
return app;
}
所以最后還是通過Instrumentation.makeApplication()實例化的,這個老板娘真的很厲害呀!
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
而且通過反射拿到Application對象之后,直接調(diào)用attach(),所以attach()調(diào)用是在onCreate()之前的。
參考文章
下面的這些文章都是這方面比較精品的,希望你抽出時間研究,這可能需要花費很長時間,但是如果你想進階為中高級開發(fā)者,這一步是必須的。
再次感謝下面這些文章的作者的分享精神。
Binder
zygote
ActivityThread、Instrumentation、AMS
- Android Activity.startActivity流程簡介
- Android應用程序進程啟動過程的源代碼分析
- 框架層理解Activity生命周期(APP啟動過程)
- Android應用程序窗口設計框架介紹
- ActivityManagerService分析一:AMS的啟動
- Android應用程序窗口設計框架介紹
Launcher
結語
OK,到這里,這篇文章算是告一段落了,我們再回頭看看一開始的幾個問題,你還困惑嗎?
- 一個App是怎么啟動起來的?
- App的程序入口到底是哪里?
- Launcher到底是什么神奇的東西?
- 聽說還有個AMS的東西,它是做什么的?
- Binder是什么?他是如何進行IPC通信的?
- Activity生命周期到底是什么時候調(diào)用的?被誰調(diào)用的?
再回過頭來看看這些類,你還迷惑嗎?
- ActivityManagerServices,簡稱AMS,服務端對象,負責系統(tǒng)中所有Activity的生命周期
- ActivityThread,App的真正入口。當開啟App之后,會調(diào)用main()開始運行,開啟消息循環(huán)隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一起完成Activity的管理工作
- ApplicationThread,用來實現(xiàn)ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關Application中的Activity的生命周期時,通過ApplicationThread的代理對象與ActivityThread通訊。
- ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的。
- Instrumentation,每一個應用程序只有一個Instrumentation對象,每個Activity內(nèi)都有一個對該對象的引用。Instrumentation可以理解為應用進程的管家,ActivityThread要創(chuàng)建或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作。
- ActivityStack,Activity在AMS的棧管理,用來記錄已經(jīng)啟動的Activity的先后關系,狀態(tài)信息等。通過ActivityStack決定是否需要啟動新的進程。
- ActivityRecord,ActivityStack的管理對象,每個Activity在AMS對應一個ActivityRecord,來記錄Activity的狀態(tài)以及其他的管理信息。其實就是服務器端的Activity對象的映像。
- TaskRecord,AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord。AMS用TaskRecord確保Activity啟動和退出的順序。如果你清楚Activity的4種launchMode,那么對這個概念應該不陌生。
如果你還感到迷惑的話,就把這篇文章多讀幾遍吧,信息量可能比較多,需要慢慢消化~
尊重原創(chuàng),轉(zhuǎn)載請注明:From 凱子哥(http://blog.csdn.net/zhaokaiqiang1992) 侵權必究!
關注我的微博,可以獲得更多精彩內(nèi)容
<a target="_blank"><img border="0" src="http://service.t.sina.com.cn/widget/qmd/1783932377/a0641c19/10.png"/></a>