ActivityStarter封装了一个activity启动的过程(包括上下文环境),不采用情景栈分析法真的很难分析,这里采用情景分析法把该函数分析. 整体代码如下:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
//1. 初始化环境和lunchModeFlags
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
//2. 复用activity逻辑
mReusedActivity = getReusableIntentActivity();
......
if (mReusedActivity != null) {
......
mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
......
setTaskFromIntentActivity(mReusedActivity);
if (!mAddingToTask && mReuseTask == null) {
resumeTargetStackIfNeeded();
return START_TASK_TO_FRONT;
}
}
.......
//singleTop 或者singleInstance的处理
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly resumed the top activity.
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
......
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
......
return START_DELIVERED_TO_TOP;
}
//3. 设置对应task并带到前台
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
setTaskFromReuseOrCreateNewTask(taskToAffiliate);
......
} else if (mSourceRecord != null) {
......
final int result = setTaskFromSourceRecord();
......
} else if (mInTask != null) {
......
final int result = setTaskFromInTask();
if (result != START_SUCCESS) {
return result;
}
} else {
setTaskToCurrentTopOrCreateNewTask();
}
// 4. 启动Activity
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
// 5. 使Activity可见
if (mDoResume) {
if (!mLaunchTaskBehind) {
mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
}
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
.... . .
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
......
return START_SUCCESS;
}
我们先整体介绍下这里activity启动的过程
- 计算启动的flags,首先计算flags是因为后面要根据flags选择启动的task,所以这一步是铺垫作用.这里读者可能会问为什么要计算,因为有些flags是冲突的,所以需要计算一下.
- 对于找到task的过程其实还包含一些特殊的activity模式和标志的处理,以及对activity复用的逻辑.可以复用的情况包含如下几种
- LaunchSingleInstance
- LaunchSingleTask
- (singleTop|FLAG_ACTIVITY_SINGLE_TOP) && activity已经在已经在栈顶. 对于在栈顶这一条,如果指定了FLAG_ACTIVITY_NEW_TASK标志或者要启动的activity模式为LaunchSingleInstance或者 LaunchSingleTask的activity,又或者mOptions.getLaunchTaskId()指定了taskId(这个优先级要高于参数中指定的inTask).其实可以先把其他的符合复用条件的task放到栈顶.所以在复用之前还有根据条件将复用的task带到前台的环节. 对于activity复用后这些activity是不用启动的,之需要使他们可见可以返回了,还第5步有着类似的逻辑
- 计算在哪个task中启动,这里可定是有四种种情况了
- 新创建一个task启动 (指定了FLAG_ACTIVITY_NEW_TASK标志,没有找到复用的task)
- 在sourceRecord(也就是调用startActivity的activity),没有指定FLAG_ACTIVITY_NEW_TASK标志,并且sourceRecord不为空
- 在指定的task中启动, 一般是用于恢复task
- 在当前焦点stack的topTask中启动 , 既没有FLAG_ACTIVITY_NEW_TASK,又没有指定task并且还没有mSourceRecord,这种情况根据注释说不会发生
- 在锚定task并把它带到前台之后就可以启动activity了,使用 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions)
- mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions) 使activity可见
下面就围绕这4步对代码进行展开说明
一.对启动参数进行初始化,主要是下面三个函数
- setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
setInitialState 函数比较简单,主要初始化了如下变量
- mStartActivity 要启动的Activity的ActivityRecord.
- mIntent 调用者传递的intent
- mOptions 调用者传递的额外参数,主要用于动画和task,stack,display等额外信息的传递
- mCallingUid 调用者uid
- mSourceRecord 调用者activity
- mLaunchBounds 打掉主要给PIP模式使用,指定activity的大小
- mLaunchSingleTop 要启动的activity是否为singleTop模式的activity
- mLaunchSingleInstance: singleInstance模式的activity
- mLaunchSingleTask : singleTask模式的activity
- mLaunchFlags : 这个值通过adjustLaunchFlagsToDocumentMode计算,主要是通过intent中传递的flags与在AndroidManifest.xml中配置的lunchMode和documentLaunchMode做一些处理,并把DocumentMode转化为lunchModeFlags,操作如下:
private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
boolean launchSingleTask, int launchFlags) {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(launchSingleInstance || launchSingleTask)) {
launchFlags &=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
switch (r.info.documentLaunchMode) {
case ActivityInfo.DOCUMENT_LAUNCH_NONE:
break;
case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case Acti