Activity的啓動流程有倆種過程,一種是根Activity的啓動過程,即在Launch界面點擊一個應用圖標啓動應用程序,根Activity指的是應用程序啓動的第一個Activity;另外一種是普通Activity的啓動流程,即咱們平時調用startActivity方法來啓動一個Activity。本文討論第二種,startActivity方法你們都知道是用來啓動一個Activity的,那麼你們有沒有想過它在底層是怎麼啓動的呢?Activity的生命週期方法是如何被回調的?它啓動過程當中涉及到多少個進程?接下來咱們經過擼一篇源碼來了解Activity的大概啓動流程,而後解答這幾個問題。html
本文源碼基於Android8.0,本文涉及的源碼文件位置以下:
frameworks/base/core/java/android/app/Activity.java
frameworks/base/services/core/java/com/android/server/am/*.java(*表明ActivityManagerService,ActivityStack,ActivityStarter,ActivityStackSupervisor,ActivityStack)
複製代碼
startActivity有好幾種重載方法,以下:java
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
//咱們通常沒有傳options參數給startActivity,因此options爲空,就會走到這個分支
//第二參數requestCode爲-1,表示不須要知道Activity啓動的結果
startActivityForResult(intent, -1);
}
}
//發現兩個參數的startActivityForResult方法最終仍是調用三個參數的startActivityForResult方法,options參數傳入null
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
複製代碼
能夠發現startActivity最終都會調用到startActivityForResult方法。android
這裏咱們來到了具備三個參數的startActivityForResult方法,以下:git
//Activity.java
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
//mParent一直爲空
if (mParent == null) {
//...
//一、關注這裏,調用Instrumentation的execStartActivity方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
//...
//此時requestCode爲-1
if (requestCode >= 0) {
mStartedActivity = true;
}
//...
} else {
//...
}
複製代碼
在上面的的代碼中,會進入mParent==null的這個分支裏,mParent是Activity類型,它只會在LocalActivityManger構造中被賦值,在咱們startActivity過程當中一直爲空(關於爲甚麼mParent一直爲空,能夠查看這篇文章StartActivity路上的mParent)。這裏咱們只關注註釋1,調用Instrumentation的execStartActivity方法,Instrumentation是一個用來監控應用程序與系統交互的類,咱們還要注意傳入execStartActivity方法的兩個參數:數組
//ActivityThread.java::ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
//...
}
複製代碼
IApplicationThread.java類是在編譯時由IApplicationThread.aidl經過AIDL工具自動生成的,IApplicationThread的內部會自動生成一個 IApplicationThread.Stub類,它繼承自Binder類,而Binder實現了IBinder接口,而且 IApplicationThread.Stub實現了IActivityManager接口。要想進行進程間通訊,ApplicationThread只須要繼承IApplicationThread.Stub類並實現相應的方法就能夠,這樣主線程ActivityThread就能夠經過ApplicationThread就能對外提供遠程服務。要記住這個ApplicationThread,他在Activity的啓動過程當中發揮重要做用。架構
咱們繼續看Instrumentation的execStartActivity方法,以下:app
//Instrumentation.java
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
//還記得上面提到的ApplicationThread嗎,這裏把它轉成了IApplicationThread,並在下面做爲startActivity方法的參數
IApplicationThread whoThread = (IApplicationThread) contextThread;
//...
try {
//...
//一、關注這裏,這裏實際調用的是ActivityManagerService的startActivity方法
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//檢查啓動Activity的結果,沒法正確啓動一個Activiy時,這個方法拋出異常
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
複製代碼
咱們看註釋1,ActivityManager.getService()返回的是ActivityManagerService(下面簡稱AMS)在應用進程的本地代理,該方法在ActivityManager中,以下:ide
//ActivityManager.java
public static IActivityManager getService() {
//IActivityManagerSingleton是Singleton類型,Singleton是一個單例的封裝類
//第一次調用它的get方法時它會經過create方法來初始化AMS這個Binder對象,在後續調用中返回以前建立的對象
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//ServiceManager是服務大管家,這裏經過getService獲取到了IBinder類型的AMS引用
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//這經過asInterface方法把IBinder類型的AMS引用轉換成AMS在應用進程的本地代理
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
複製代碼
上面出現的IActivityManager.java類的意義相似於前面提到的ApplicationThread.java。要想進行進程間通訊,AMS只須要繼承IActivityManager.Stub類並實現相應的方法就能夠,這樣AMS就能對外提供遠程服務,以下:工具
//ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
//...
}
複製代碼
因此繼續回到Instrumentation的execStartActivity方法中,ActivityManager.getService()返回的是AMS的本地代理,注意AMS是在系統進程SystemServer中,因此註釋1這裏經過Binder的IPC,調用的實際上是AMS的startActivity方法。ui
整個過程的時序圖以下:
在這裏開始,Activity的啓動過程從應用進程轉移到AMS中去。
AMS的startActivity方法以下:
//AMS.java
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
複製代碼
簡單的return了startActivityAsUser方法,該方法在最後多了個 UserHandle.getCallingUserId()參數,AMS根據這個肯定調用者權限。咱們再來看看其餘參數:
下面繼續看AMS的startActivityAsUser方法。
startActivityAsUser方法以下:
//AMS.java
public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
//...
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
複製代碼
省略了兩個判斷,一、判斷調用者進程是否被隔離,二、判斷調用者是否有權限,這些都不是重點。下面繼續簡單的return了mActivityStarter.startActivityMayWait方法,mActivityStarter是ActivityStarter類型,它是AMS中加載Activity的控制類,會收集全部的邏輯來決定如何將Intent和Flags轉換爲Activity,並將Activity和Task以及Stack相關聯。傳入startActivityMayWait方法的參數又多了幾個,看一下幾個:
下面看ActivityStarter中的startActivityMayWait方法。
來看看這個方法的源碼,以下:
//ActivityStarter.java
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 globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask, String reason) {
//...
//把上面傳進來的intent再構造一個新的Intent對象,這樣即使intent被修改也不受影響
intent = new Intent(intent);
//...
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
if(rInfo == null){
//...
}
//解析這個intent,收集intent指向的Activity信息
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
//...
final ActivityRecord[] outRecord = new ActivityRecord[1];
//一、主要關注這裏,調用了自己的startActivityLocked方法
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason);
//...
return res;
}
複製代碼
ActivityInfo裏面收集了要啓動的Activity信息(關於ResolveInfo與ActivityInfo能夠看這篇如何獲取Android應用與系統信息),主要仍是關注註釋1,這裏又調用了ActivityStarter中的startActivityLocked方法。傳入startActivityLocked方法的參數又多了幾個(callingPid等)。關於pid於與uid的介紹能夠看這篇文章Android手機中UID、PID做用及區別。
下面來看一下startActivityLocked方法。
該方法的相關源碼以下:
//ActivityStarter.java
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) {
//這裏對上面傳進來值爲"startActivityAsUser"理由參數判空
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
//一、主要關注這裏,調用了自己的startActivity方法
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
if (outActivity != null) {
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}
複製代碼
這裏主要關注註釋1,調用了ActivityStarter中的startActivity方法,該方法多了一個參數,最後一個mLastStartActivityRecord,mLastStartActivityRecord是一個ActivityRecord數組類型,ActivityRecord是用來保存一個Activity的全部信息的類。
下面來看ActivityStarter中的startActivity方法。
//ActivityStarter.java
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//...
//獲取調用者所在進程記錄的對象,caller就是上面一直強調的表明調用者進程的ApplicationThread對象
ProcessRecord callerApp = null;
if (caller != null) {
//這裏調用AMS的getRecordForAppLocked方法得到表明調用者進程的callerApp
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//獲取調用者進程的pid與uid並賦值
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
err = ActivityManager.START_PERMISSION_DENIED;
}
}
//下面startActivity方法的參數之一,表明調用者Activity的信息
ActivityRecord sourceRecord = null;
if (resultTo != null) {
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
//...
}
//...
//建立即將要啓動的Activity的信息描述類ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
//outActivity是ActivityRecord[]類型,從上面傳進來,這裏把ActivityRecord賦值給了它,下面會做爲參數傳進startActivity方法中
if (outActivity != null) {
outActivity[0] = r;
}
//...
//一、關注這裏,調用了自己的另外一個startActivity方法
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
複製代碼
上面的startActivity代碼很是長,省略了不少,上面講的調用者進程,在這裏等價於應用程序進程,ProcessRecord是用來描述一個應用進程的信息,ActivityRecord上面也講過了,就是用來記錄一個要啓動的Activity的全部信息,在註釋1處的調用了ActivityStarter的startActivity方法,這個方法參數少了不少,大多數有關要啓動的Activity的信息都被封裝進了ActivityRecord類中,做爲參數r傳了進去。
下面來看ActivityStarter的startActivity方法。
該方法代碼以下:
//ActivityStarter.java
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
//一、主要關注這裏,調用自己的startActivityUnchecked方法
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
//...
mService.mWindowManager.continueSurfaceLayout();
}
//...
return result;
}
複製代碼
這裏主要調用了ActivityStarter的startActivityUnchecked方法。
該方法代碼以下:
//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
//把上面傳進來的參數除了outActivity都傳進去了,主要是把這些參數賦值給ActivityStarter的成員變量,如mDoResume = doResume, mStartActivity = r
//mStartActivity就是即將要啓動的Activity的信息
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
//計算出啓動Activity的模式,並賦值給mLaunchFlags
computeLaunchingTaskFlags();
//...
//設置啓動模式
mIntent.setFlags(mLaunchFlags);
//...
boolean newTask = false;
//一、下面會進行判斷,到底需不須要建立一個新的Activity任務棧
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
//1.1走這裏就會在setTaskFromReuseOrCreateNewTask方法內部建立一個新的Activity任務棧
newTask = true;
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
//1.2走這裏就會在setTaskFromSourceRecord方法內部得到調用者Activity的的任務棧賦值給mTargetStack
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
//1.3走這裏就會在setTaskFromInTask方法內部直接把mInTask賦值給mTargetStack,前面已經說過mInTask等於null
result = setTaskFromInTask();
} else {
//1.四、就是前面的條件都不知足了,可是這種狀況不多發生
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
//...
//mDoResume等於上面傳進來的doResume,爲true
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
//走這裏不會顯示Activity,由於Activity尚未獲取焦點或者Activity的棧溢出
//...
} else {
//正常的話會走到這裏
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
//二、主要關注這裏調用mSupervisor的resumeFocusedStackTopActivityLocked方法
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
//...
}
return START_SUCCESS;
}
複製代碼
上面的startActivityUnchecked方法也是很長,這個方法主要處理Activity棧管理相關的邏輯,若是對於這方面信息不熟悉的話能夠查看這兩篇文章Android任務和返回棧徹底解析、ActivityTask和Activity棧管理。一個或多個ActivityRecord會組成一個TaskRecord,TaskRecord用來記錄Activity的棧,而ActivityStack包含了一個或多個TaskRecord。上面代碼的mTargetStack就是ActivityStack類型,咱們先來看註釋1,註釋1會根據mLaunchFlags等條件到底需不須要建立一個新的Activity任務棧,而本文所討論的條件限定在從一個應用程序調用Activity的startActivity去啓動另一個Activity的情景,並且默認Activity的啓動模式是standard,並不會建立一個新的任務棧,因此就會走到1.2的條件分支,而後咱們再來看註釋2,這裏會調用mSupervisor.resumeFocusedStackTopActivityLocked方法,mSupervisor是ActivityStackSupervisor類型,ActivityStackSupervisor主要用來管理ActivityStack。啓動Activity的過程從ActivityStack來到了ActivityStackSupervisor。
下面咱們來看ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法。
該方法源碼以下:
//ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
//...
//獲取要啓動的Activity所在棧的棧頂的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
//一、r是否null或是否爲RESUMED狀態
if (r == null || r.state != RESUMED) {
//二、關注這裏,調用ActivityStack的resumeTopActivityUncheckedLocked方法
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
複製代碼
首先這裏會獲取要啓動的Activity所在棧的棧頂的ActivityRecord賦值給r,由於要啓動的Activity的尚未啓動,因此此時棧頂就是調用者Activity,調用者Activity啓動Activity,確定會從RESUME狀態轉到其餘狀態如STPO,因此註釋1知足r.state != RESUMED的條件,此時就是走帶註釋2,註釋2調用了mFocusedStack的resumeTopActivityUncheckedLocked方法,mFocusedStack就是ActivityStack類型。啓動Activity的過程從ActivityStackSupervisor又回到到了ActivityStack。
下面咱們來看ActivityStack的resumeTopActivityUncheckedLocked方法。
該方法的源碼以下:
//ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
//...
boolean result = false;
try {
//一、關注這裏,這裏調用了自己的resumeTopActivityInnerLocked方法
result = resumeTopActivityInnerLocked(prev, options);
} finally {
//...
}
//...
return result;
}
複製代碼
咱們來看註釋1,簡單的調用了resumeTopActivityInnerLocked方法。
該方法源碼以下:
//ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//...
//得到將要啓動的Activity的信息
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */)
//...
if (next.app != null && next.app.thread != null) {
//...
}else{
//...
//一、關注這裏,調用了ActivityStackSupervisor的startSpecificActivityLocked方法
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
複製代碼
topRunningActivityLocked方法得到將要啓動的Activity的信息next,由於此時要啓動的Activity還不屬於任何進程,故它的ProcessRecord爲空成立,就會走到else分支,因此註釋1這裏調用了ActivityStackSupervisor的startSpecificActivityLocked方法,又回到了ActivityStackSupervisor中。
下面來看ActivityStackSupervisor的startSpecificActivityLocked方法。
該方法源碼以下:
//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
//獲取要啓動的Activity的所在應用程序進程
ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//要啓動的Activity的所在應用程序進程存在
if (app != null && app.thread != null) {
try {
//...
//一、關注這裏,調用了自己的realStartActivityLocked方法
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
//...
}
}
//...
}
複製代碼
這裏首先會獲取要啓動的Activity所在的應用進程app,當app進程已經運行時,就會調用註釋1處的realStartActivityLocked方法,注意這裏多了一個參數,把表明應用進程的app傳了進去。
下面來看ActivityStackSupervisor的realStartActivityLocked方法。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
//...
//一、把應用所在進程信息賦值給要啓動的Activity的ActivityRecord
r.app = app;
//...
try{
//...
//二、關注這裏,app是ProcessRecord類型,app.thread是IApplicationThread類型
//app.thread是應用進程的ApplicationThread在AMS的本地代理,前面已經講過
//因此這裏實際調用的是ApplicationThread的scheduleLaunchActivity方法
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
//...
}catch (RemoteException e) {
//...
}
//...
return true;
}
複製代碼
正如這方法名所示,realStartActivity,兜兜轉轉,這裏就是真正啓動Activity的地方,註釋1處app指的是傳入的要啓動的Activity的所在的應用程序進程,是從前面傳過來的,這裏把它賦值給了要啓動的Activity的ActivityRecord的app字段去,這樣就能夠說要啓動的Activity屬於應用進程,咱們再來看註釋2這裏,app.thread就是咱們上面一直強調的ApplicationThread,因此這裏經過Binder的IPC其實調用的是ApplicationThread中的scheduleLaunchActivity方法。
整個過程的時序圖以下:
當前的代碼邏輯執行在AMS所在進程,從這裏開始Activity的啓動流程最終又回到了應用進程所在的ApplicationThread中。
原本一篇文章寫完Activity的啓動,寫到這裏才發現,篇幅太長,因此Activity在應用進程中的啓動過程就放到下一篇文章。本文簡單的介紹了應用進程請求AMS啓動Activity過程和Activity在AMS中的啓動過程,如今讓咱們來回答一下開頭給出的幾個問題:
從應用調用一個startActivity方法開始,應用進程開始請求AMS啓動Activity,而後在AMS中Activity完成它的一系列準備,最後再回到應用進程中開始回調Activity的生命週期,本文回答了一半這個問題,即本文講解了應用進程開始請求AMS啓動Activity,而後在AMS中完成它的一系列準備的過程,這個過程用時序圖表示以下:
本文並無解答這個問題,這個問題要到下一篇文章纔能有答案。
答案是2個,前言已經講過本文討論的是普通Activity的啓動流程,即咱們平時調用startActivity方法來啓動一個Activity,因此本文這個過程涉及的進程能夠能夠用下面這個圖表示:
圖中AppProcess表明應用所在進程,systemServer表明AMS所在進程,兩個進程之間經過Binder進行通訊,實現了XX.Stub的類就能夠進行Binder通訊,如本文的ApplicationThread和AMS都實現了各自的Stub類,因此應用進程startActivity時請求AMS啓動Activity,AMS準備好後,再發送scheduleLaunchActivity請求告訴應用能夠開始啓動Activity了。
那麼若是是前言所講的第一種啓動Activity的過程,即在Launch界面點擊一個應用圖標啓動應用程序,那麼會涉及多少個進程?答案是4個,如圖:
能夠看到會涉及Launcher進程、SystemServer進程、App進程、Zygote進程。關於這些進程的簡單信息能夠看這篇從進程的角度看Android的系統架構
閱讀源碼真的是一個漫長的過程,又時候看別人寫的那麼簡單,可是當本身去寫,才發現要考慮的東西不少,因此這是一個日積月累的過程,因此閱讀源碼的時候,最好跟着前人的文章閱讀,這樣理解的更快。
參考文章:
《Android開發藝術探索》