當我們在一個Activity中(或通過Context物件),呼叫startActivity()方法來啟動另一個Activity的程序中發生了什么呢?這就是本文想跟大家分享的內容,我們一起通過原始碼的方式來看下Activity的啟動程序,(本文是基于Android Q的原始碼)
?Activity的啟動流程大體分為兩步:找到要啟動的Activity;然后啟動它,(雖說有點像如何把大象裝進冰箱,但也確實是那么回事,只不過每個步驟有更多細節)
找到Activity
?要想啟動一個Activity,系統先要找到這個Activity的資訊,我們以從一個Activity中啟動另一個Activity為起點來分析Activity的啟動程序,在這個程序種會涉及到系統查找要啟動的Activity的程序,下面我們以時序圖來分析Activity的啟動程序:

? 這只是Activity啟動程序種的一小部分,Activity的啟動的服務端是由ActivityTaskManagerService實作的,在ActivityTaskManagerService中Activity的啟動又是由ActivityStarter來實作,對于系統如何找到要啟動的Activity,大體分為兩步:
- 得到ResolveInfo物件,實作方式是通過ActivityStackSuperVisor.resolveIntent()方法(最終是呼叫了PackageManagerService.resolveIntent()方法)決議而來;
- 得到ActivityInfo物件,在得到ResolveInfo物件后,加上一些邏輯判斷得到ActivityInfo物件;至此系統就找到了需要啟動的Activity;
而這兩步都是在ActivityStarter.startActivityMayWait()方法中完成,
//ActivityStarter.java
private int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
// Refuse possible leaked file descriptors
// 省略部分代碼....
// Save a copy in case ephemeral needs it
final Intent ephemeralIntent = new Intent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
if (componentSpecified
&& !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
&& !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
&& !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
&& mService.getPackageManagerInternalLocked()
.isInstantAppInstallerComponent(intent.getComponent())) {
intent.setComponent(null /*component*/);
componentSpecified = false;
}
// 通過ActivitySuperVisor.resolveIntent()方法決議得到ResolveInfo物件;
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
if (rInfo == null) {
UserInfo userInfo = mSupervisor.getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
UserManager userManager = UserManager.get(mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = userManager.getProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null)
&& userManager.isUserUnlockingOrUnlocked(parent.id)
&& !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
}
}
}
//得到ActivityInfo物件
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
synchronized (mService.mGlobalLock) {
final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
stack.mConfigWillChange = globalConfig != null
&& mService.getGlobalConfiguration().diff(globalConfig) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
mService.mHasHeavyWeightFeature) {
// This may be a heavy-weight process! Check to see if we already
// have another, different heavy-weight process running.
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final WindowProcessController heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.mInfo.uid != aInfo.applicationInfo.uid
|| !heavy.mName.equals(aInfo.processName))) {
int appCallingUid = callingUid;
if (caller != null) {
WindowProcessController callerApp =
mService.getProcessController(caller);
if (callerApp != null) {
appCallingUid = callerApp.mInfo.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
SafeActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, "android",
appCallingUid, userId, null, null, 0, new Intent[] { intent },
new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
if (requestCode >= 0) {
// Caller is requesting a result.
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
heavy.updateIntentForHeavyWeightActivity(newIntent);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setFlags(intent.getFlags());
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
resolvedType = null;
caller = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
componentSpecified = true;
rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
0 /* matchFlags */, computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
aInfo = rInfo != null ? rInfo.activityInfo : null;
if (aInfo != null) {
aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
}
}
}
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
allowBackgroundActivityStart);
Binder.restoreCallingIdentity(origId);
//省略部分代碼
return res;
}
}
啟動Activity
?在了解系統怎么找到要啟動的Activity后,我們現在就來看下啟動Activity的程序,在了解Activity啟動程序前,我們先了解下Activity 堆疊結構模型
Activity結構模型
下面這幅圖就是Activity(對應圖中的ActivityRecord)在歷史任務中的結構,

資料結構描述
- RootActivityContainer : Activity 容器的根節點
- ActivityDisplay:每個實體代表系統中的一個顯示螢屏,也就是說如果你的Android設備是多屏的,那么將會有多個ActivityDisplay實體,
- ActivityStack: Activity堆疊,用于表示管理堆疊中的Activity,
- TaskRecord:ActivityRecord串列的封裝類,在ActivityStack中用于記錄歷史運行的Activity,
- ActivityRecord:ActivityRecord表示歷史運行的Activity物件,
- 通過
dumpsys activity a命令可查看當前設備的activity堆疊結構,
啟動程序分析
對于上面的資料結構圖,要有個基本掌握,這有助于我們理解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,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
WindowProcessController callerApp = null;
if (caller != null) {
callerApp = mService.getProcessController(caller);
if (callerApp != null) {
callingPid = callerApp.getPid();
callingUid = callerApp.mInfo.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
final int userId = aInfo != null && aInfo.applicationInfo != null
? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
ActivityRecord sourceRecord = null;
//resultRecord用于記錄接收啟動Activity的結果(要記住這個方法是從Activity.startActivityForResult()呼叫下來的)
ActivityRecord resultRecord = null;
//這里的resultTo取決于是否是Activity(Activity中重寫了Context.startActivity()方法)物件啟動,
//如果是Activity則resulTo為該Activity在Activity堆疊中的ActivityRecord實體,否則為null
if (resultTo != null) {
//如果在ActivityA 中啟動ActivityB,那么這個sourceRecord實際上就是ActivityA在Activity堆疊中的ActivityRecord實體;
sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
//......省略部分ActivityInfo和權限判斷代碼......
//創建ActivityRecord物件
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, checkedOptions, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
if (r.appTimeTracker == null && sourceRecord != null) {
// If the caller didn't specify an explicit time tracker, we want to continue
// tracking under any it has.
r.appTimeTracker = sourceRecord.appTimeTracker;
}
final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
// If we are starting an activity that is not from the same uid as the currently resumed
// one, check whether app switches are allowed.
if (voiceSession == null && (stack.getResumedActivity() == null
|| stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp));
}
ActivityOptions.abort(checkedOptions);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
mService.onStartActivitySetDidAppSwitch();
mController.doPendingActivityLaunches(false);
//呼叫另一個startActivity多載方法,該方法會呼叫startActivityUnchecked()方法,
final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
return res;
}
?在此方法中主要完成以下事情:
-
要啟動的Activity包名類名是否存在以及權限的判斷;
-
創建要啟動的Activity所對應的ActivityRecord物件
?接下來,我們看下startActivityUnchecked()方法,這個方法很長也很復雜,我們把Activity啟動分為以下幾種情況來分析:
-
將Activity加入到現有的TaskRecord中,且Activity堆疊中已經有要啟動的Activity對應的ActivityRecord物件;
-
將Activity加入到現有的TaskRecord中,但Activity堆疊中沒有要啟動的Activity對應的ActivityRecord物件;
-
加入到新創建的TaskRecord中,
我們先看第一種方式:
//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
//重置變數并重新給mStartActivity,mIntent,mSourceRecord等變數賦值
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
final int preferredWindowingMode = mLaunchParams.mWindowingMode;
//計算得到LaunchFlag,并將結果賦值給mLaunchFlag; Flag定義見Intent.Flags注解
computeLaunchingTaskFlags();
//計算mSourceRecord所在的ActivityStack,并將得到的結果賦值給mSourceStack變數
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
//getReusableIntentActivity()方法主要是判斷要啟動的Activity對應的ActivityRecord物件是否可以放入已有的TaskRecord中,
//如果可以則遍歷RootActivityContainer看要啟動的Activity對應的ActivityRecord是否已經存在,如果存在則回傳這個物件;
//如果不存在則返要放入的TaskRecord中的頂層ActivityRecord
ActivityRecord reusedActivity = getReusableIntentActivity();
mSupervisor.getLaunchParamsController().calculate(
reusedActivity != null ? reusedActivity.getTaskRecord() : mInTask,
r.info.windowLayout, r, sourceRecord, options, PHASE_BOUNDS, mLaunchParams);
mPreferredDisplayId =
mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
: DEFAULT_DISPLAY;
if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info,
mPreferredDisplayId, true /* allowInstrumenting */)) {
Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
return START_CANCELED;
}
if (reusedActivity != null) {
if (mService.getLockTaskController().isLockTaskModeViolation(
reusedActivity.getTaskRecord(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
// True if we are clearing top and resetting of a standard (default) launch mode
// ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
// 如果launchMode為standard,且intent flag設定了FLAG_ACTIVITY_CLEAR_TOP或FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,
// 則clearTopAndResetStandardLaunchMode為true
final boolean clearTopAndResetStandardLaunchMode =
(mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
== (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
&& mLaunchMode == LAUNCH_MULTIPLE;
// 如果目標ActivityRecord的TaskRecor為null,且clearTopAndResetStandardLaunchMode為true
// 則設定目標ActivityRecord的TaskRecord.
if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
mStartActivity.setTask(reusedActivity.getTaskRecord());
}
if (reusedActivity.getTaskRecord().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTaskRecord().setIntent(mStartActivity);
} else {
final boolean taskOnHome =
(mStartActivity.intent.getFlags() & FLAG_ACTIVITY_TASK_ON_HOME) != 0;
//判斷是否存在FLAG_ACTIVITY_TASK_ON_HOME標簽,如果存在且有FLAG_ACTIVITY_NEW_TASK標簽,
//啟動這個Activity后會將Launcher所在的ActivityStack拉到當前所啟動的Activity所在ActivityStack后面,
//舉例,應用A啟動應用B中的某個Activity,且設定的launchFlag包含FLAG_ACTIVITY_TASK_ON_HOME和FLAG_ACTIVITY_NEW_TASK;
//當應用B退出的時候并不會回到應用A,而是回到Launcher應用,
if (taskOnHome) {
reusedActivity.getTaskRecord().intent.addFlags(FLAG_ACTIVITY_TASK_ON_HOME);
} else {
reusedActivity.getTaskRecord().intent.removeFlags(FLAG_ACTIVITY_TASK_ON_HOME);
}
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
// as the first operation, in case the activity will be resumed as a result of later
// operations.
// 三種clear top的情況:1,launchFlag包含FLAG_ACTIVITY_CLEAR_TOP;2,launchFlag包含FLAG_ACTIVITY_NEW_DOCUMENT
// 且不包含FLAG_ACTIVITY_MULTIPLE_TASK;3,launchMode為singleInstance或者singleTask
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
final TaskRecord task = reusedActivity.getTaskRecord();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
// state.
// 將要啟動的Activity所對應的ActivityRecord以上的物件從task中的ActivityRecord串列中移除
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
// The above code can remove {@code reusedActivity} from the task, leading to the
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
if (reusedActivity.getTaskRecord() == null) {
reusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.getTaskRecord().setIntent(mStartActivity);
}
//如果堆疊頂的Activity就是需要啟動的Activity,則呼叫Activity的onNewIntent()方法
deliverNewIntent(top);
}
}
mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded
(false /* forceSend */, reusedActivity);
//setTargetStackAndMoveToFrontIfNeeded()和resumeTargetStackIfNeeded()方法的呼叫會將Activity堆疊中的
//reusedActivity拉起并顯示到前臺,當然這個程序也會涉及到將前臺應用調到后臺,
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
if (reusedActivity != null) {
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
// The reusedActivity could be finishing, for example of starting an
// activity with FLAG_ACTIVITY_CLEAR_TOP flag. In that case, return the
// top running activity in the task instead.
outActivity[0] = reusedActivity.finishing
? reusedActivity.getTaskRecord().getTopActivity() : reusedActivity;
}
//這種情況是Activity已經被啟動過,ActivityRecord實體存在于TaskRecord中,
//一種場景就是我們啟動一個應用的MainActivity后,按home鍵回到launcher后再進入這個應用,走的就是這個流程
return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
}
}
}
//.....省略部分代碼.......
}
?注釋中已經做了部分說明,這里有個比較重要的方法getReusableIntentActivity(),這個方法是判斷要啟動的ActivityRecord是否加入到現有的TaskRecord中,這個判斷會涉及到launchMode、taskAffinity和launchFlag的設定,這里我們就不展開了,以后的文章我們再來詳細了解,這里我們先舉個例子說明:
<activity android:name="com.example.ltst.MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.ltst.activity.ActivitySingleTaskCustomAffinity"
android:taskAffinity=".singleTaskAffinity"
android:launchMode="singleTask"/>
<activity android:name="com.example.ltst.activity.ActivitySingleTask"
android:launchMode="singleTask">
</activity>
<activity android:name="com.example.ltst.activity.ActivitySingleInstance"
android:launchMode="singleInstance"/>
<activity android:name="com.example.ltst.activity.ActivityStandard"/>
?如上所示,我們定義了五個Activity,現在從MainActivity中分別啟動另外四個Activity:
- MainActivity > ActivitySingleTaskCustomAffinity, MainActivity的taskAffinity為默認的包名,ActivitySingleTaskCustomeAffinity自定義了taskAffinity,所以這種情況
getReusableIntentActivity()回傳為null. - MainActivity > ActivitySingleTask,MainActivity和ActivitySingleTask的launchMode和taskAffinity(不顯示定義的話默認為應用包名)都是一樣的,這個時候
getReusableIntentActivity()回傳的就是MainActivity的ActivityRecord物件; - MainActivity > ActivitySingleInstance,launchMode為singleInstance比較特殊,該模式下TaskRecord下只能有一個ActivityRecord,由于ActivitySingleInstance對應的TaskRecord還沒有被創建過,所以此時
getReusableIntentActivity()回傳的也是null, - MainActivity > ActivityStandard, 這種情況
getReusableIntentActivity回傳的是nul,這是因為getReusableIntentActivity()里面有判斷要啟動Activity的launchMode和launchFlag,如果launchFlag沒有設定FLAG_ACTIVITY_NEW_TASK且launchMode不為singleInstance和singleTask,則會回傳null,但這也不是意味著ActivityStandard會被放入其他的TaskRecord中,它還是會被加入到MainActivity所在的TaskRecord中,
對于已經被啟動過的Activity,且它對應的ActivityRecord還在ActivityStack中的時候,再次啟動該Activity的流程(也就是App熱啟動的情況)大概是這樣的:

?在ActivityStack.resumeTopActivityInnerLocke()方法中會觸發一個ResumeActivityItem請求的事務,最后事務處理會執行ResumeActivityItem.excute()方法中的任務,ResumeActivityItem.excute()方法會呼叫ActivityThread.handleResuemActivity().
?如上面的例子中所述,對于創建新的TaskRecord有多種情況,我們來看另一種情況——App冷啟動,這種情況會涉及到ActivityStack和TaskRecord的創建,
//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
//重置變數并重新給mStartActivity,mIntent,mSourceRecord等變數賦值
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
//.......省略部分代碼....
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getActivityStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
final ActivityRecord topFocused = topStack.getTopActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.mActivityComponent.equals(mStartActivity.mActivityComponent)
&& top.mUserId == mStartActivity.mUserId
&& top.attachedToProcess()
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
// This allows home activity to automatically launch on secondary display when
// display added, if home was the top activity on default display, instead of
// sending new intent to the home activity on default display.
&& (!top.isActivityTypeHome() || top.getDisplayId() == mPreferredDisplayId);
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
deliverNewIntent(top);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTaskRecord(), preferredWindowingMode,
mPreferredDisplayId, topStack);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTaskRecord() : null;
// Should this be considered a new task?
int result = START_SUCCESS;
// 下面的幾個判斷是計算要啟動的ActivityRecord所存放的ActivityStack,mTargetStack會被正確的賦值,
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {//冷啟動會進入該條件
newTask = true;
//setTaskFromReuseorCreateNewTask()會創建ActivityStack
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
result = setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId);
mService.getPackageManagerInternalLocked().grantEphemeralAccess(
mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid),
UserHandle.getAppId(mCallingUid));
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
mStartActivity.getTaskRecord().taskId);
}
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTaskRecord());
mTargetStack.mLastPausedActivity = null;
mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
false /* forceSend */, mStartActivity);
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTaskRecord().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
} else {
if (mTargetStack.isFocusable()
&& !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mRootActivityContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
} else if (mStartActivity != null) {
mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
}
mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
preferredWindowingMode, mPreferredDisplayId, mTargetStack);
return START_SUCCESS;
}
?冷啟動的情況下,setTaskFromReuseOrCreateNewTask會創建要啟動的Activity對應的ActivityRecord所在的Activitystack和TaskRecord,然后經過mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);實作啟動Activity的邏輯;RootActivityContainer.resumeFocusedStacksTopActivities()方法最侄訓呼叫ActivityStack.resumeTopActivityInnerLocked(), 啟動Activity的主要邏輯就在該方法中,這個方法比較長,我們只截取部分說明
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}
if (DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityInnerLocked: ", new RuntimeException("resumeTopActivityInnerLocked").fillInStackTrace());
// next即要啟動的Activity
ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && !isAttached()) {
return false;
}
mRootActivityContainer.cancelInitializingActivities();
boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else.
return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
}
next.delayedResume = false;
final ActivityDisplay display = getDisplay();
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.isState(RESUMED)
&& display.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
return false;
}
if (!next.canResumeByCompat()) {
return false;
}
if (shouldSleepOrShutDownActivities()
&& mLastPausedActivity == next
&& mRootActivityContainer.allPausedActivitiesComplete()) {
boolean nothingToResume = true;
if (!mService.mShuttingDown) {
final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
&& next.canShowWhenLocked();
final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
&& next.mAppWindowToken != null
&& next.mAppWindowToken.containsDismissKeyguardWindow();
if (canShowWhenLocked || mayDismissKeyguard) {
ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
!PRESERVE_WINDOWS);
nothingToResume = shouldSleepActivities();
}
}
if (nothingToResume) {
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
return false;
}
}
if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.mUserId + " is stopped");
return false;
}
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything until that is done.
if (!mRootActivityContainer.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
return false;
}
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
boolean lastResumedCanPip = false;
ActivityRecord lastResumed = null;
final ActivityStack lastFocusedStack = display.getLastFocusedStack();
if (lastFocusedStack != null && lastFocusedStack != this) {
lastResumed = lastFocusedStack.mResumedActivity;
if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
+ " next=" + next + " lastResumed=" + lastResumed);
userLeaving = false;
}
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
"resumeTopActivity", userLeaving /* beforeStopping */);
}
// 如果Intent設定了FLAG_RESUME_WHILE_PAUSING 且上個Activity不以分屏的方式顯示,則resumeWhilePasuing為true
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip;
// 在啟動Activity前先要讓堆疊中的Activity進入pause狀態,如果有Activity進入pause狀態則pausing為true
boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
//如果有Activity進入了pause狀態且resumeWhilePasuing為false,這個時候就會return,
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, false /* updateOomAdj */);
}
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
&& display.allResumedActivitiesComplete()) {
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
return true;
}
//.....省略部分代碼......
}
?上面截取的是讓activity 堆疊中的Activity先進入pause狀態的邏輯,這也是為什么應用A啟動應用B的時候,應用A的Activity的onPause()方法會在應用B的Activity的onCreate()方法之前呼叫(這里沒有考慮分屏的情況),getDisplay().pauseBackStacks(userLeaving, next, false);會讓前臺App的Activity進入pause狀態,該方法會呼叫到ActivityStack.startPausingLocked()方法,在這個方法中主要的邏輯是發送一個PauseActivityItem的事務,
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
if (!shouldSleepActivities()) {
completePauseLocked(false, resuming);
}
}
ActivityRecord prev = mResumedActivity;
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return false;
}
if (prev == resuming) {
Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
return false;
}
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
mPausingActivity = prev;
mLastPausedActivity = prev;
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.setState(PAUSING, "startPausingLocked");
prev.getTaskRecord().touchActiveTime();
clearLaunchTime(prev);
mService.updateCpuStats();
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
if (mPausingActivity != null) {
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else if (DEBUG_PAUSE) {
Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
}
if (pauseImmediately) {
completePauseLocked(false, resuming);
return false;
} else {
schedulePauseTimeout(prev);
return true;
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return false;
}
}
或許你有個疑問,既然這個地方直接return ture了,那ActivityStarter.startActivityUnchecked()呼叫是否就已經結束了呢;答案是肯定的,那你肯定又有疑問了,既然方法呼叫都結束了,那Activity到底是怎么啟動的呢,因為目前只講到了pause 之前應用的Activity,還沒講到啟動Activity,要回答這個問題,這就看下pause Activity是怎么實作的了,先放張時序圖,感興趣的同學去跟一跟代碼,

?上面的時序圖主要分為兩個步驟:
-
將前臺應用A退入后臺,實作的程序是在PauseActivityItem.excute()方法中呼叫ActivityThread.handlePauseActivity()方法;
-
當應用A退入到后臺后,將應用B顯示到前臺,實作程序是PauseActivityItem.postExcute()中呼叫ActivityTaskManagerService.activityPaused(),然后經過一系列方法呼叫,最后執行到了ActivityStack.resumeTopActivityInnerLocked()方法,這個方法我們前面講過,只不過前面是在
if (pausing && !resumeWhilePausing)條件下return 了;而這個時候下會呼叫ActivitySupervisor.startSpecificActivityLocked(),startSpecificActivityLocked()會呼叫realStartActivityLocked()方法,
我們先看下startSpecificActivityLocked()方法
//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
//如果Activity所屬的行程已經創建,則啟動Activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
knownToBeDead = true;
}
if (getKeyguardController().isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
//如果行程沒有創建,則創建行程,PooledLambda.obtainMessage回傳一個會呼叫
//ActivityManagerInternal.startProcess(mService.mAmInternal, r.processName, r.info.applicationInfo,
//knownToBeDead, "activity", r.intent.getComponent())的Callback,
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
?App冷啟動的程序會執行創建行程的程序,限于篇幅的原因,這里就不展開了,下次我們單獨講解,上面的時序圖也省略了行程創建的程序,同樣我們下次再補上,雖然這里省略了行程創建的程序,但是行程創建過后,也同樣會呼叫realStartActivtiyLocked()方法來繼續執行啟動Activity,我們看下realStartActivityLocked()個方法:
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
//.....省略部分代碼......
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
//.....省略部分代碼......
return true;
}
這個方法的核心是啟動一個設定了LaunchActivityItem回呼和ResumeActivityItem請求的事務,有了前面的經驗我們知道,最終LauncherActivityItem和ResumeActivityItem的execute()方法會被執行,我們看下他們的execute()方法實作:
//LaunchActivityItem.java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
//ResumeActivityItem.java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
?方法很簡單,分別呼叫了ActivityThread.handleLauncheActivity()、ActivityThread.handleResumeActivity();這兩個方法最侄訓呼叫到Activity的onCreate()、onResume()方法,這個時候你可能就有疑問了,那onStart()方法呢,不是應該在onResume之前呼叫的嗎,這個就要從TransactionExecutor.execute()說起,我們看下這個方法
//TransactionExecutor.java
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
//.....省略部分代碼....
//先執行callback,也就是會先執行LaunchActivityItem.execute()方法
executeCallbacks(transaction);
//然后呼叫executeLifecyleState()方法,這個方法會處理事務中的請求事件,
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
//在呼叫ActivityLifeCycleItem(ResumeActivityItem的父類)的execute()方法之前,先呼叫cycleToPath()方法;
//lifecycleItem.getTargetState()即為ResumeActivityItem.getTargetState()回傳的值3(ON_RESUME).
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
@VisibleForTesting
public void cycleToPath(ActivityClientRecord r, int finish, ClientTransaction transaction) {
cycleToPath(r, finish, false /* excludeLastState */, transaction);
}
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
//經過execute()中執行executeCallbacks(transaction)后,Activity就處于ON_CTREATE狀態,這個時候start值為1(ON_CREATE),
final int start = r.getLifecycleState();
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Cycle activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " from: " + getStateName(start) + " to: " + getStateName(finish)
+ " excludeLastState: " + excludeLastState);
}
//這個時候start = 1,finish = 3, excludeLastState = true;mHelper.getLifecyclePath方法會回傳只有一個元素(值為2)的整型陣列物件
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
performLifecycleSequence(r, path, transaction);
}
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
//這個時候state就是`mHelper.getLifecyclePath(start, finish, excludeLastState);`回傳的陣列中的元素值2(ON_START)
//所以這時候會呼叫ActivityThread.handleStartActivity()方法,最終Activity.onStart()方法會被呼叫,
switch (state) {
//ON_CREATE、ON_START、ON_RESUEM、ON_PAUSE、ON_STOP、ON_DESTROY、ON_RESTART
//定義在ActivityLifecycleItem.java中,他們的值分別為:0、1、2、3、4、5、6、7
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(r.token, false /* show */,
0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r.token, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
?代碼中注釋已經做了說明了,總結下就是在呼叫ResumeActivityItem.execute()方法之前,會先執行cycleToPath()判斷Activity的起始狀態和目標狀態,如果后者大于前者,則需要執行兩者之間的狀態,至此冷啟動情況下啟動Activity就分析完了, 至于Activity啟動后顯示的程序可以參照下之前的文章《Activity UI顯示流程分析》,當然還有很多細節沒有展開,比如ActivityStack、TaskRecord的創建和更新,以及行程創建的程序;這寫以后有機會再分享,大家也可以自己研究,文中的時序圖可作為參考,
結束
?最后我們稍稍總結下,Activity啟動程序主要分為兩個程序:一是找到這個Activity(得到ActivityRecord物件);二是啟動它,而啟動程序又分為兩種情況:一種在Activity堆疊中有Activity對應的ActivityRecord物件(這個會跟launchMode和launch flag有關),這種情況會走Activity的onNewIntent()方法;另一種是Activity堆疊中沒有Activity對應的ActivityRecord,這種情況下又可分為多種子情況,但是我們不比糾結每種情況的細節;文中我們是分析了冷啟動一個App的情況,雖然行程創建程序沒有展開,但是后面Activity的啟動流程還是一致的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/292373.html
標籤:其他
上一篇:監聽adapter里兩個按鈕
