activity是Android中最爲重要的組件之一,幾乎全部的Android應用都離不開Activity的支撐。所以瞭解activity的啓動流程,掌握activity的工做原理,對於咱們應用層開發人員來講是很是有意義的。本文對activity的整個啓動流程作了一下整理,但願能對你們有所幫助。java
注:本文基於Android8.0.0源碼編寫android
Activity的啓動主要能夠分爲兩種狀況:markdown
不管是上述哪一種狀況,實際上都是經過調用Activity類的startActivity方法(或是調用startActivityForResult方法來但願新頁面可以返回一個結果)來啓動新的Activity。所以,想要理清activity的啓動流程,咱們首先就要從startActivity方法開始入手。app
startActivity方法的源碼以下:ide
源碼路徑:\frameworks\base\core\java\android\app\Activity.java public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
複製代碼
能夠看到,startActivity方法最終也會走到startActivityForResult方法中。startActivityForResult源碼以下:post
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
...
//註釋1
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
複製代碼
註釋1處的代碼是startActivityForResult方法的核心代碼,該行代碼將啓動activity的工做交給了一個Instrumentation對象。Instrumentation是應用和系統交互的一箇中介,接下來咱們就來看一下Instrumentation的execStartActivity方法:ui
源碼路徑:\frameworks\base\core\java\android\app\Instrumentation.java public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
...
}
複製代碼
在閱讀execStartActivity方法以前,咱們須要先看一下該方法所接受的參數,咱們將該方法接收的參數和在startActivityForResult方法中調用該方法時傳入的內容進行一下對比,以便搞清這些參數的含義:this
//調用時傳入的參數
execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
//方法的定義
execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options)
複製代碼
經過對比咱們不難猜出這些參數的含義:spa
搞懂了這些參數的含義,咱們再來看execStartActivity的內容,能夠看到在execStartActivity方法中主要是調用了ActivityManager.getService().startActivity來進一步執行啓動activity的工做。咱們先來看一下ActivityManager.getService()究竟返回的是什麼:線程
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//註釋2
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
複製代碼
經過分析源碼咱們能夠發現,getService返回的是一個IActivityManager對象,而且該對象使用了單例模式。在註釋2處,首先經過ServiceManager.getService來獲取了一個IBinder,而後經過IActivityManager.Stub.asInterface(b)這行代碼將這個Binder對象轉化爲了IActivityManager類型。有了解過AIDL的實現方式的同窗應該不能看出,IActivityManager.Stub.asInterface正是標準的AIDL實現方式,而這裏獲取到的這個IActivityManager對象,正是系統服務ActivityManagerService的本地代理對象。
ActivityManagerService(簡稱AMS)是Android系統的一個很是重要的系統服務,它是在android系統啓動時建立的,並由SystemService進行管理。AMS主要負責管理android系統中各應用的activity頁面,控制activity對象的生命週期等,所以,當咱們的應用進程要啓動一個新的Activity時,天然要和AMS進行通訊。從上面的代碼能夠看出,8.0以後的系統使用的是AIDL來和AMS進行通訊的(注:在8.0以前是並非使用的AIDL)。
當經過ActivityManager.getService()獲取到了這個IActivityManager對象以後,又調用了該對象的startActivity方法,因爲這個IActivityManager其實是AMS在客戶端的一個代理,所以此處其實是調用的AMS的startActivity方法。至此,android的啓動由應用進程進入到了AMS進程中。
咱們來看一下AMS的startActivity方法的源碼:
源碼路徑:\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
@Override
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());
}
@Override
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");
}
複製代碼
能夠看到,在startActivity中調用了startActivityAsUser方法,在startActivityAsUser中又調用了mActivityStarter的startActivityMayWait方法,咱們來看一下startActivityMayWait方法的源碼:
源碼路徑:\frameworks\base\services\core\java\com\android\server\am\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) {
...
synchronized (mService) {
...
final ActivityRecord[] outRecord = new ActivityRecord[1];
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);
...
}
...
}
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) {
...
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);
...
return mLastStartActivityResult;
}
複製代碼
startActivityMayWait方法的代碼很長,但最核心的代碼則是調用了startActivityLocked方法來進一步啓動Activity,而在startActivityLocked方法中又調用了startActivity方法,startActivity方法源碼以下:
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) {
...
//註釋1
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
...
//註釋2
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
複製代碼
在註釋1處,系統將要被啓動的Activity的各種信息封裝到了一個ActivityRecord對象中。ActivityRecord是activity在AMS中的一個記錄,能夠理解爲每一個ActivityRecord都表明着一個Activity實體。以後,在註釋2處又調用了另外一個startActivity的重載方法,咱們看一下該方法的源碼:
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();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
}
...
return result;
}
複製代碼
能夠看到startActivity方法又調用了startActivityUnchecked方法:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
...
// 註釋1: 若是要被啓動的activity和當前在棧頂的activity是同一個
// 那麼須要檢查要被啓動的activity是否只容許被啓動一次
final ActivityStack topStack = mSupervisor.mFocusedStack;//獲取當前最頂部的activity棧
final ActivityRecord topFocused = topStack.topActivity();//獲取當前棧頂的activity
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
// 判斷是否應該啓動一個新的activity
// 若是要啓動的activity和當前棧頂的activity是同一個,而且要啓動的activity的啓動模式爲
// FLAG_ACTIVITY_SINGLE_TOP,則不須要進行啓動
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
...
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
...
return START_DELIVERED_TO_TOP;
}
...
//註釋2:檢查是否應該建立一個新的activity任務棧
// 在啓動模式設置爲FLAG_ACTIVITY_NEW_TASK的狀況下會新建一個activity任務棧來存放要啓動的activity
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//建立新任務棧
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
//使用發起請求的activity的任務棧來存放要被啓動的activity
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
}
...
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
//註釋3
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
...
return START_SUCCESS;
}
複製代碼
startActivityUnchecked方法的代碼較長,但邏輯並不複雜。先來看註釋1處的幾行代碼,這裏主要是爲了處理要被啓動的activity的啓動模式爲SINGLE_TOP的狀況。在註釋1處,首先獲取了當前處於棧頂的activity的信息,而後判斷要被啓動的activity和當前處於棧頂的activty是不是同一個。若是要被啓動的activity和當前處於棧頂的actiivty是同一個activity,而且要被啓動的activity的啓動模式被設置爲了FLAG_ACTIVITY_SINGLE_TOP,那麼系統不會繼續去從新啓動一個新的activity實例,而是直接複用當前棧頂的activity,並返回START_DELIVERED_TO_TOP,後面的代碼也不會再執行了。
註釋2處的代碼主要是用來判斷要被啓動的activity是否要放入到一個新的任務棧中。咱們都知道,若是activity的啓動模式被設置爲了NEW_TASK,那麼該activity會被放入一個單獨的任務棧中。從註釋2出的代碼咱們能夠看出,若是要被啓動的activity被設置了FLAG_ACTIVITY_NEW_TASK標識,那麼系統會爲該activity建立一個新的activity任務棧。
以後系統會判斷要被啓動的activity是否能夠獲取焦點等信息,而後經過註釋3處的代碼來繼續啓動activity,咱們來看一下mSupervisor的resumeFocusedStackTopActivityLocked方法。
代碼路徑:\frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
//註釋1
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//註釋2
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
...
return false;
}
複製代碼
在註釋1處,若是targetStack不爲null而且targetStack擁有焦點,那麼會執行targetStack的resumeTopActivityUncheckedLocked方法。 在註釋2處獲取到了棧中正在運行的最頂端的一個ActivityRecord,若是r爲null或者r的狀態不是RESUMED,則會執行 mFocusedStack的resumeTopActivityUncheckedLocked方法。targetStack和mFocusedStack都是ActivityStack類型的對象,咱們來看一下ActivityStack的resumeTopActivityUncheckedLocked方法:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
try {
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
}
...
return result;
}
複製代碼
resumeTopActivityUncheckedLocked方法又調用了resumeTopActivityInnerLocked方法:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
//註釋1
pausing |= startPausingLocked(userLeaving, false, next, false);
}
...
if (next.app != null && next.app.thread != null) {
...
} else {
...
//註釋2
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
複製代碼
在註釋1處,若是當前存在已經處於前臺展現的activity,則會先調用startPausingLocked方法將當前處於展現狀態的activity轉爲pasue狀態。
在一般狀況下,代碼會執行到註釋2處,此處調用了mStackSupervisor對象的startSpecificActivityLocked方法來繼續activity的啓動,該方法源碼以下:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
//註釋1:根據要被啓動的activity的信息獲取其所在的進程信息
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//註釋2:若是要啓動的activity的所在進程存在
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//註釋3
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
//註釋4
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
複製代碼
在註釋1處,系統首先根據要被啓動的activity的信息來獲取其所在的進程的信息,在註釋2處對獲取到的app對象進行了判斷,若是app不位null而且app的thread(即ActivityThread)也不爲空,說明要啓動的activity的進程存在,那麼會調用註釋3處的realStartActivityLocked方法來進一步啓動activity,不然會調用註釋4處的startProcessLocked方法來建立一個新進程。
建立新進程的過程比較複雜,會放在以後的文章中進行專門介紹,這裏先來看進程已經存在的狀況。realStartActivityLocked源碼以下:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
...
try {
...
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);
...
}
...
return true;
}
複製代碼
在realStartActivityLocked方法中直接調用了app.thread.scheduleLaunchActivity來啓動Activity。app即要啓動的activity所在的進程,thread即該進程的ActivityThread,這是一個Binder對象,所以,app.thread.scheduleLaunchActivity其實是跨進程調用,實際上調用的是要啓動的activity所在進程的ActivityThread對象中的scheduleLaunchActivity方法。至此,activity的啓動流程就從AMS中轉到了目標應用進程中。
咱們對這部分的啓動流程進行一下歸納總結: