Activity啓動過程
一些基本的概念
- ActivityManagerServices,簡稱AMS,服務端對象,負責系統中所有Activity的生命週期
- ActivityThread,App的真正入口。當開啓App之後,會調用main()開始運行,開啓消息循環隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一起完成Activity的管理工作
- ApplicationThread,用來實現ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關Application中的Activity的生命週期時,通過ApplicationThread的代理對象與ActivityThread通訊。
- ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的。
- Instrumentation,每一個應用程序只有一個Instrumentation對象,每個Activity內都有一個對該對象的引用。Instrumentation可以理解爲應用進程的管家,ActivityThread要創建或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作。
- ActivityStack,Activity在AMS的棧管理,用來記錄已經啓動的Activity的先後關係,狀態信息等。通過ActivityStack決定是否需要啓動新的進程。
- ActivityRecord,ActivityStack的管理對象,每個Activity在AMS對應一個* ActivityRecord,來記錄Activity的狀態以及其他的管理信息。其實就是服務器端的Activity對象的映像。
- TaskRecord,AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord。AMS用TaskRecord確保Activity啓動和退出的順序。如果你清楚Activity的4種launchMode,那麼對這個概念應該不陌生。
回答一些問題
zygote是什麼?有什麼作用?
zygote意爲“受精卵“。Android是基於Linux系統的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。
在Android系統裏面,zygote是一個進程的名字。Android是基於Linux System的,當你的手機開機的時候,Linux的內核加載完成之後就會啓動一個叫“init“的進程。在Linux System裏面,所有的進程都是由init進程fork出來的,我們的zygote進程也不例外。
我們都知道,每一個App其實都是
- 一個單獨的dalvik虛擬機
- 一個單獨的進程
所以當系統裏面的第一個zygote進程運行之後,在這之後再開啓App,就相當於開啓一個新的進程。而爲了實現資源共用和更快的啓動速度,Android系統開啓新進程的方式,是通過fork第一個zygote進程實現的。所以說,除了第一個zygote進程,其他應用所在的進程都是zygote的子進程,這下你明白爲什麼這個進程叫“受精卵”了吧?因爲就像是一個受精卵一樣,它能快速的分裂,並且產生遺傳物質一樣的細胞!
SystemServer是什麼?有什麼作用?它與zygote的關係是什麼?
首先我要告訴你的是,SystemServer也是一個進程,而且是由zygote進程fork出來的。
知道了SystemServer的本質,我們對它就不算太陌生了,這個進程是Android Framework裏面兩大非常重要的進程之一——另外一個進程就是上面的zygote進程。
爲什麼說SystemServer非常重要呢?因爲系統裏面重要的服務都是在這個進程裏面開啓的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是不是都挺眼熟的?
那麼這些系統服務是怎麼開啓起來的呢?
在zygote開啓的時候,會調用ZygoteInit.main()進行初始化
public static void main(String argv[]) {
...ignore some code...
//在加載首個zygote的時候,會傳入初始化參數,使得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,服務端對象,負責系統中所有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...
//加載本地系統服務庫,並進行初始化
System.loadLibrary("android_servers");
nativeInit();
// 創建系統上下文
createSystemContext();
//初始化SystemServiceManager對象,下面的系統服務開啓都需要調用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...
}
//初始化系統上下文對象mSystemContext,並設置默認的主題,mSystemContext實際上是一個ContextImpl對象。調用ActivityThread.systemMain()的時候,會調用ActivityThread.attach(true),而在attach()裏面,則創建了Application對象,並調用了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);
// 現在電源管理已經開啓,ActivityManagerService負責電源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
經過上面這些步驟,我們的ActivityManagerService對象已經創建好了,並且完成了成員變量初始化。而且在這之前,調用createSystemContext()創建系統上下文的時候,也已經完成了mSystemContext和ActivityThread的創建。注意,這是系統進程開啓時的流程,在這之後,會開啓系統的Launcher程序,完成系統界面的加載與顯示。
你是否會好奇,我爲什麼說AMS是服務端對象?下面我給你介紹下Android系統裏面的服務器和客戶端的概念。
其實服務器客戶端的概念不僅僅存在於Web開發中,在Android的框架設計中,使用的也是這一種模式。服務器端指的就是所有App共用的系統服務,比如我們這裏提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎的系統服務是被所有的App公用的,當某個App想實現某個操作的時候,要告訴這些系統服務,比如你想打開一個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通過調用startActivity()並不能直接打開另外一個App,這個方法會通過一系列的調用,最後還是告訴AMS說:“我要打開這個App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進程來fork一個新進程,來開啓我們的目標App的。這就像是瀏覽器想要打開一個超鏈接一樣,瀏覽器把網頁地址發送給服務器,然後還是服務器把需要的資源文件發送給客戶端的。
知道了Android Framework的客戶端服務器架構之後,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通信呢?
知道了Android Framework的客戶端服務器架構之後,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通信呢?
App與AMS通過Binder進行IPC通信,AMS(SystemServer進程)與zygote通過Socket進行IPC通信。
那麼AMS有什麼用呢?在前面我們知道了,如果想打開一個App的話,需要AMS去通知zygote進程,除此之外,其實所有的Activity的開啓、暫停、關閉都需要AMS來控制,所以我們說,AMS負責系統中所有Activity的生命週期。
在Android系統中,任何一個Activity的啓動都是由AMS和應用程序進程(主要是ActivityThread)相互配合來完成的。AMS服務統一調度系統中所有進程的Activity啓動,而每個Activity的啓動過程則由其所屬的進程具體來完成。
這樣說你可能還是覺得比較抽象,沒關係,下面有一部分是專門來介紹AMS與ActivityThread如何一起合作控制Activity的生命週期的。
Launcher是什麼?什麼時候啓動的?
當我們點擊手機桌面上的圖標的時候,App就由Launcher開始啓動了。但是,你有沒有思考過Launcher到底是一個什麼東西?
Launcher本質上也是一個應用程序,和我們的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實現了點擊、長按等回調接口,來接收用戶的輸入。既然是普通的App,那麼我們的開發經驗在這裏就仍然適用,比如,我們點擊圖標的時候,是怎麼開啓的應用呢?如果讓你,你怎麼做這個功能呢?捕捉圖標點擊事件,然後startActivity()發送對應的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大量使用標籤來實現界面的複用,而且定義了很多的自定義控件實現界面效果,dock_divider從佈局的參數聲明上可以猜出,是底部操作欄和上面圖標佈局的分割線,而paged_view_indicator則是頁面指示器,和App首次進入的引導頁下面的界面引導是一樣的道理。當然,我們最關心的是Workspace這個佈局,因爲註釋裏面說在這裏麪包含了5個屏幕的單元格,想必你也猜到了,這個就是在首頁存放我們圖標的那五個界面(不同的ROM會做不同的DIY,數量不固定)。
接下來,我們應該打開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的基礎之上,添加了一些特效,比如你長按移動圖標的時候,圖標位置會出現一個背景(不同版本的效果不同),所以我們找到BubbleTextView對象的點擊事件,就可以找到Launcher如何開啓一個App了。
除了在桌面上有圖標之外,在程序列表中點擊圖標,也可以開啓對應的程序。這裏的圖標使用的不是BubbleTextView對象,而是PagedViewIcon對象,我們如果找到它的點擊事件,就也可以找到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...
}
}
從上面的代碼我們可以看到,在桌面上點擊快捷圖標的時候,會調用
startActivitySafely(v, intent, tag);
那麼從程序列表界面,點擊圖標的時候會發生什麼呢?實際上,程序列表界面使用的是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..
}
}
}
可以看到,調用的是
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
殊途同歸
不管從哪裏點擊圖標,調用的都是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;
}
調用了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;
}
這裏會調用Activity.startActivity(intent, opts.toBundle()),這個方法熟悉嗎?這就是我們經常用到的Activity.startActivity(Intent)的重載函數。而且由於設置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以這個Activity會添加到一個新的Task棧中,而且,startActivity()調用的其實是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);
}
}
所以我們現在明確了,Launcher中開啓一個App,其實和我們在Activity中直接startActivity()基本一樣,都是調用了Activity.startActivityForResult()。
Instrumentation是什麼?和ActivityThread是什麼關係?
還記得前面說過的Instrumentation對象嗎?每個Activity都持有Instrumentation對象的一個引用,但是整個進程只會存在一個Instrumentation對象。當startActivityForResult()調用之後,實際上還是調用了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) {
//當現在的Activity有父Activity的時候會調用,但是在startActivityFromChild()內部實際還是調用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()的實現
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;
}
所以當我們在程序中調用startActivity()的 時候,實際上調用的是Instrumentation的相關的方法。
Instrumentation意爲“儀器”,我們先看一下這個類裏面包含哪些方法吧
我們可以看到,這個類裏面的方法大多數和Application和Activity有關,是的,這個類就是完成對Application和Activity初始化和生命週期的工具類。比如說,我單獨挑一個callActivityOnCreate()讓你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對activity.performCreate(icicle);這一行代碼熟悉嗎?這一行裏面就調用了傳說中的Activity的入口函數onCreate(),不信?接着往下看
Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒騙你吧,onCreate在這裏調用了吧。但是有一件事情必須說清楚,那就是這個Instrumentation類這麼重要,爲啥我在開發的過程中,沒有發現他的蹤跡呢?
是的,Instrumentation這個類很重要,對Activity生命週期方法的調用根本就離不開他,他可以說是一個大管家,但是,這個大管家比較害羞,是一個女的,管內不管外,是老闆娘~
那麼你可能要問了,老闆是誰呀?
老闆當然是大名鼎鼎的ActivityThread了!
ActivityThread你都沒聽說過?那你肯定聽說過傳說中的UI線程吧?是的,這就是UI線程。我們前面說過,App和AMS是通過Binder傳遞信息的,那麼ActivityThread就是專門與AMS的外交工作的。
AMS說:“ActivityThread,你給我暫停一個Activity!”
ActivityThread就說:“沒問題!”然後轉身和Instrumentation說:“老婆,AMS讓暫停一個Activity,我這裏忙着呢,你快去幫我把這事辦了把~”
於是,Instrumentation就去把事兒搞定了。
所以說,AMS是董事會,負責指揮和調度的,ActivityThread是老闆,雖然說家裏的事自己說了算,但是需要聽從AMS的指揮,而Instrumentation則是老闆娘,負責家裏的大事小事,但是一般不拋頭露面,聽一家之主ActivityThread的安排。
如何理解AMS和ActivityThread之間的Binder通信?
前面我們說到,在調用startActivity()的時候,實際上調用的是
mInstrumentation.execStartActivity()
但是到這裏還沒完呢!裏面又調用了下面的方法
ActivityManagerNative.getDefault()
.startActivity