本文原创作者:Cloud Chou. 出处:本文链接

本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究。

前面两篇博客介绍了Activity的详细启动流程,提到ActivityStack类的startActivityUncheckedLocked方法负责调度ActivityRecord和Task,并且调度算法非常复杂,需结合实际场景分析调度算法。本篇博客将介绍startActivityUncheckedLocked方法的具体实现,本结合实际场景分析调度算法。

final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
//...
//如果从Launcher程序启动应用,launchFlags为
//FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
//否则一般情况下launcheFlags为0,除非启动Activity时设置了特殊的flag
int launchFlags = intent.getFlags();
//启动Activity时默认不会设置FLAG_ACTIVITY_PREVIOUS_IS_TOP
//故此notTop默认情况下会是null
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
//...默认情况下这里的代码不会执行
}
//根据被启动的Activity和sourceRecord设置标志
//launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK
//如果从通知栏启动应用 sourceRecord == null
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from non-Activity context;"
+"forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
+ intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
// own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
// The activity being started is a single instance... it always
// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} //一般情况下r.resultTo 不为null,它是启动该Activity的Activity,
//如果从通知栏启动Activity 则r.result为null
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...
r.resultTo = null;
}
//addingToTask 如果为true表示正在添加至某个task,
// 后续需要将r添加至sourceRecord所在的task
boolean addingToTask = false;
//movedHome表示是否移动home task
boolean movedHome = false;
//reuseTask 如果不为null,则表示已存在task,会重用这个task,
// 但是这个Task里的所有Activity会被清除掉,
// 需要将r加入这个task
TaskRecord reuseTask = null;
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//从通知栏启动时r.resultTo == null
//如果launchFlags设置了FLAG_ACTIVITY_NEW_TASK,r.resultTo也会为null
if (r.resultTo == null) {
//查找ActivityRecord栈,看要启动的activity是否已有相关task,
//如果已经有相关task,则不需要创建新的task,可以使用已有的task
//如果要启动的activity的启动模式是LAUNCH_SINGLE_INSTANCE,
//则使用快速查找方法findTaskLocked,否则使用慢速查找方法findActivityLocked
//因为如果启动模式是LAUNCH_SINGLE_INSTANCE,则这个activity只会在一个单独的Task里
//故此查找时,可以以task为单位进行查找和比较,这样比较快
//查找得到的结果taskTop是相关task的栈顶的ActivityRecord
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
//找到了相关task
if (taskTop != null) {
//重设task的intent
if (taskTop.task.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.
taskTop.task.setIntent(intent, r.info);
}
//如果目标task不在栈顶,
//则先将Home task移动到栈顶(实际上只有当启动Activity设置的Flag同时设置了
//FLAG_ACTIVITY_TASK_ON_HOME和FLAG_ACTIVITY_NEW_TASK才会移动home task,
//否则不会移动home task),
//然后再将目标task移动到栈顶
// If the target task is not in the front, then we need
// to bring it to the front... except... well, with
// SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop != null && curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
boolean callerAtFront = sourceRecord == null
|| curTop.task == sourceRecord.task;
if (callerAtFront) {
// We really do want to push this one into the
// user's face, right now.
movedHome = true;
moveHomeToFrontFromLaunchLocked(launchFlags);
moveTaskToFrontLocked(taskTop.task, r, options);
options = null;
}
}
//如果launchFlags设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,则会重置task
//从Launcher应用程序启动应用会设置FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
// If the caller has requested that the target task be
// reset, then do so.
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
taskTop = resetTaskIfNeededLocked(taskTop, r);
}
//... 一般情况下startFlags 不会设置 START_FLAG_ONLY_IF_NEEDED
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
//...
}
// ==================================
//默认情况下不会设置 Intent.FLAG_ACTIVITY_CLEAR_TASK
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
// The caller has requested to completely replace any
// existing task with its new activity. Well that should
// not be too hard...
reuseTask = taskTop.task;
performClearTaskLocked(taskTop.task.taskId);
reuseTask.setIntent(r.intent, r.info);
} else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//默认情况下launchFlags不会设置FLAG_ACTIVITY_CLEAR_TOP
//但是如果被启动的activity的启动模式是singleTask或者singleInstance,
//也会进入该分支
// 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.
//清除r所在的task 在r之上的所有activity,
//该task里r和在r下的activity不会被清除
ActivityRecord top = performClearTaskLocked(
taskTop.task.taskId, r, launchFlags);
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.task.setIntent(r.intent, r.info);
}
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent);
} else {
// A special case: we need to
// start the activity because it is not currently
// running, and the caller has asked to clear the
// current task to have this activity at the top.
addingToTask = true;
// Now pretend like this activity is being started
// by the top of its task, so it is put in the
// right place.
sourceRecord = taskTop;
}
} else if (r.realActivity.equals(taskTop.task.realActivity)) {
// In this case the top activity on the task is the
// same as the one being launched, so we take that
// as a request to bring the task to the foreground.
// If the top activity in the task is the root
// activity, deliver this new intent to it if it
// desires.
if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
&& taskTop.realActivity.equals(r.realActivity)) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
if (taskTop.frontOfTask) {
taskTop.task.setIntent(r.intent, r.info);
}
taskTop.deliverNewIntentLocked(callingUid, r.intent);
} else if (!r.intent.filterEquals(taskTop.task.intent)) {
// In this case we are launching the root activity
// of the task, but with a different intent. We
// should start a new instance on top.
addingToTask = true;
sourceRecord = taskTop;
}
} else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
// In this case an activity is being launched in to an
// existing task, without resetting that task. This
// is typically the situation of launching an activity
// from a notification or shortcut. We want to place
// the new activity on top of the current task.
addingToTask = true;
sourceRecord = taskTop;
} else if (!taskTop.task.rootWasReset) {
//进入该分支的情况比较少
// In this case we are launching in to an existing task
// that has not yet been started from its front door.
// The current task has been brought to the front.
// Ideally, we'd probably like to place this new task
// at the bottom of its stack, but that's a little hard
// to do with the current organization of the code so
// for now we'll just drop it.
taskTop.task.setIntent(r.intent, r.info);
}
// ================================== end
//如果没有正在添加至某个Task, 并且不用加入一个已清除所有Activity的Task
//此时只需要显示栈顶Activity即可
if (!addingToTask && reuseTask == 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.
if (doResume) {
resumeTopActivityLocked(null, options);
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_TASK_TO_FRONT;
}
}
}
}
//...
if (r.packageName != null) {
// 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.
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
//singleTop启动模式或者singleTask启动模式,
//并且task栈顶的activity是要启动的activity,则先显示Activity
//然后调用该Activity的onNewIntent方法
logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
//先显示Activity
if (doResume) {
resumeTopActivityLocked(null);
}
ActivityOptions.abort(options);
if ((startFlags&ActivityManager.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 ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
//然后调用已显示activity的onNewIntent方法
top.deliverNewIntentLocked(callingUid, r.intent);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
} } else {
if (r.resultTo != null) {
sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return ActivityManager.START_CLASS_NOT_FOUND;
}
boolean newTask = false;
boolean keepCurTransition = false;
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (reuseTask == null) {
//创建新的task
// todo: should do better management of integers.
mService.mCurTask++;
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new task " + r.task);
} else {
//重复利用先前的task,该task里的所有acitivity已经被清空
r.setTask(reuseTask, reuseTask, true);
}
newTask = true;
if (!movedHome) {
moveHomeToFrontFromLaunchLocked(launchFlags);
}
} else if (sourceRecord != null) {
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
//清除r所在task在r之上的所有task,如果r不在task里,则返回的top为null
ActivityRecord top = performClearTaskLocked(
sourceRecord.task.taskId, r, launchFlags);
keepCurTransition = true;
if (top != null) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
//先调用onNewIntent方法 然后再显示
top.deliverNewIntentLocked(callingUid, r.intent);
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
resumeTopActivityLocked(null);
}
ActivityOptions.abort(options);
return ActivityManager.START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
//将栈里已有的activity移到栈顶
// In this case, we are launching an activity in our own task
// that may already be running somewhere in the history, and
// we want to shuffle it to the front of the stack if so.
int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
if (where >= 0) {
ActivityRecord top = moveActivityToFrontLocked(where);
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.updateOptionsLocked(options);
top.deliverNewIntentLocked(callingUid, r.intent);
if (doResume) {
resumeTopActivityLocked(null);
}
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
//同一个应用程序里的Activity A和Activity B,A可跳转至B,没有设置taskAffinity
//B的启动模式为singleTask,从A跳转至B时,B和A会在同一个task里
//该情况下会执行到这里的代码,将B的task设置为和A一样的task
r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in existing task " + r.task);
} else {
// This not being started from an existing activity, and not part
// of a new task... just put it in the top task, though these days
// this case should never happen.
final int N = mHistory.size();
ActivityRecord prev =
N > 0 ? mHistory.get(N-1) : null;
r.setTask(prev != null
? prev.task
: new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new guessed " + r.task);
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked());
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}

实际场景分析

实际场景1:

应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A和B的启动模式都为standard

1)从Launcher程序第1次启动应用时的任务调度情况:

任务调度时会创建新task并将新的ActivityRecord加入这个新的task

2)然后跳转至应用内Activity时的任务调度情况:

任务调度时会将新的ActivityRecord加入已有的task

3)然后按Home键,再打开应用程序时的调度情况:

任务调度时会先找到已有的相关task,并显示栈顶的Activity

1)从Launcher程序第1次启动应用时

会创建新task并将新的ActivityRecord加入这个新的task,任务调度执行如下所示:

final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
//...
//launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
int launchFlags = intent.getFlags();
//...
//没设置FLAG_ACTIVITY_PREVIOUS_IS_TOP,故此notTop为null
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
//...
//sourceRecord为Launcher应用的Activity launcher应用activity的启动模式为singleTask
// 故此下面的3个条件分支的内容都不会执行
if (sourceRecord == null) {
//...
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//...
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
//...
}
//...
//r.resultTo不为null, launchFlags设置了FLAG_ACTIVITY_NEW_TASK,需要将r.resultTo置为null
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...
r.resultTo = null;
}
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
//因为launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
//故此下面的条件会满足, 也就是说只要从Launcher程序启动应用,下面这个条件肯定会满足
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//...
if (r.resultTo == null) {
//因为应用被第一次启动,故此找不到相关task,taskTop则为null
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
if (taskTop != null) {
//... 这里面的内容不会执行
}
}
}
//...
//r.packageName != null
if (r.packageName != null) {
//如果被启动的Activity正好是栈顶的Activity,
//并且被启动的Activity启动模式是singleTop或者singleTask,
//则不用将新的ActivityRecord加入到栈里
//top Activity为Launcher应用的Activity
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
//top.realActivity.equals(r.realActivity)不满足
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
//... 这里的代码不会被执行
}
} } else {
//...
}
boolean newTask = false;
boolean keepCurTransition = false;
// 此时 r.resultTo为null addingToTask为false launchFlags设置了FLAG_ACTIVITY_NEW_TASK
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (reuseTask == null) {
// todo: should do better management of integers.
mService.mCurTask++;
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
//创建新task
r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new task " + r.task);
} else {
//...这里的代码会执行
}
newTask = true;
if (!movedHome) {
moveHomeToFrontFromLaunchLocked(launchFlags);
} } else if (sourceRecord != null) {
//... 这里的代码不会被执行
} else {
//...这里的代码不会被执行
}
//...
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}

2)跳转至应用内Activity时

会将新的ActivityRecord加入已有的task,任务调度执行如下所示:

final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
//此时launchFlags为0
int launchFlags = intent.getFlags();
//notTop为null
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
//...
if (sourceRecord == null) {
//...这里的代码不会被执行
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//...这里的代码不会被执行
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
//...这里的代码不会被执行
}
//r.resultTo != null 但是launchFlags未设置FLAG_ACTIVITY_NEW_TASK
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//... 这里的代码不执行
}
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
//launchFlags为0 r的启动模式为standard 故此下面的逻辑都不会执行
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//... 这里的代码不执行
}
//...
if (r.packageName != null) {
//top 是ActivityA 的ActivityRecord,
//但是被启动的Activity和top不是同一个Activity
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
//...这里的代码不执行
}
} } else {
//...这里的代码不执行
}
boolean newTask = false;
boolean keepCurTransition = false;
//此时 r.resultTo !=null sourceRecord != null addingToTask=false
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...这里的代码不执行
} else if (sourceRecord != null) {
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
//... 这里的代码不执行
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
//... 这里的代码不执行
}
//添加到现有的task
r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
//...
} else {
//... 这里的代码不执行
}
//...
return ActivityManager.START_SUCCESS;
}

3)然后按Home键,再打开应用程序

此时会先找到已有的相关task,并显示栈顶的Activity,任务调度执行如下所示:

final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
//...
//launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
int launchFlags = intent.getFlags();
//notTop为null
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
//...
if (sourceRecord == null) {
//...这里的代码不会被执行
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//...这里的代码不会被执行
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
//...这里的代码不会被执行
}
//此时 r.resultTo != null launchFlags设置了FLAG_ACTIVITY_NEW_TASK
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...
r.resultTo = null;
}
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
//此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//此时 r.resultTo == null
if (r.resultTo == null) {
//此时已有相关task,并且task 栈的栈顶是Activity B的ActivityRecord
//故此taskTop为Activity B的ActivityRecord
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
if (taskTop != null) {
//...
// 此时curTop是Launcher应用的Activity的ActivityRecord
ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop != null && curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
//此时Launcher应用的task在栈顶,故此callerAtFront为true,
//此时会把被启动的应用的task移至栈顶
boolean callerAtFront = sourceRecord == null
|| curTop.task == sourceRecord.task;
if (callerAtFront) {
// We really do want to push this one into the
// user's face, right now.
movedHome = true;
moveHomeToFrontFromLaunchLocked(launchFlags);
moveTaskToFrontLocked(taskTop.task, r, options);
options = null;
}
}
//此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
//此时需要重置task 重置完后 taskTop为ActivityB的ActivityRecord
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
taskTop = resetTaskIfNeededLocked(taskTop, r);
}
//startFlags为0
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
//... 这些代码都不会被执行
}
//根据launchFlags和被启动的activity的信息 设置resueTask addingTask变量的值
//没设置 Intent.FLAG_ACTIVITY_CLEAR_TASK
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
//... 这些代码都不会被执行
} else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//... 这些代码都不会被执行
} else if (r.realActivity.equals(taskTop.task.realActivity)) {
//... 这些代码都不会被执行
} else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
//因为从Launcher程序启动时launchFlags设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
//所以不会进入该分支
//... 这些代码都不会被执行
} else if (!taskTop.task.rootWasReset) {
//... 这些代码都不会被执行
}
//此时addingToTask为false,reuseTask为null,故此显示栈顶Actvity即可
if (!addingToTask && reuseTask == 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.
if (doResume) {
resumeTopActivityLocked(null, options);
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_TASK_TO_FRONT;
}
}
}
}
//... 以下代码都不会被执行
}

实际场景2:

应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A的启动模式都为standard,B的启动模式为singleTop

此时已从Launchenr程序打开应用,启动了Actvity A,再从A跳转至B,此时的任务调度情况:

此时不会创建新的Task,而是将B的ActivityRecord加入到A所在的task里

任务调度执行如下所示:

final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
//...
//此时launcheFlags为0
int launchFlags = intent.getFlags();
//notTop为null
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
//...这里的代码不会执行
}
//r.launchMode = ActivityInfo.LAUNCH_SINGLE_TASK
if (sourceRecord == null) {
//这里的代码不会执行
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//这里的代码不会执行
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} //此时r.resultTo!=null launchFlags设置了Intent.FLAG_ACTIVITY_NEW_TASK
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...
r.resultTo = null;
}
//addingToTask如果为true表示正在添加至某个task,后续需要将r添加至sourceRecord所在的task
boolean addingToTask = false;
//movedHome表示是否移动home task
boolean movedHome = false;
TaskRecord reuseTask = null;
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//此时 r.resultTo = null
if (r.resultTo == null) {
//此时找到的taskTop是Activity A的ActivityRecord,
//因为Actvity B和A的ActivityRecord所在的Task是相关的
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
//找到了相关task
if (taskTop != null) {
//重设task的intent
if (taskTop.task.intent == null) {
//...
}
//此时找到的task已在栈顶
ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop != null && curTop.task != taskTop.task) {
//... 这里的代码不会执行
}
//launchFlags为0
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
taskTop = resetTaskIfNeededLocked(taskTop, r);
}
//... 一般情况下startFlags 不会设置 START_FLAG_ONLY_IF_NEEDED
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
//...
} // ==================== begin
// launchFlags此时为0
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
//...这里的代码不执行
} else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
// 故此会进入该分支
//因为B还从未启动,故此得到的top为null
ActivityRecord top = performClearTaskLocked(
taskTop.task.taskId, r, launchFlags);
if (top != null) {
//...这里的代码不执行
} else {
addingToTask = true;
sourceRecord = taskTop;
}
} else if (r.realActivity.equals(taskTop.task.realActivity)) {
//...这里的代码不执行
} else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
//...这里的代码不执行
} else if (!taskTop.task.rootWasReset) {
//...这里的代码不执行
}
// ==================== end // 此时 addingToTask为true
if (!addingToTask && reuseTask == null) {
//...这里的代码不执行
}
}
}
}
//... if (r.packageName != null) {
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
//此时task还没有B的ActivityRecord,故此不会进入下述分支
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
//...这里的代码不执行
}
} } else {
//...这里的代码不执行
} boolean newTask = false;
boolean keepCurTransition = false; // 此时 r.resultTo == null addingToTask为true sourceRecord != null
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//...这里的代码不执行
} else if (sourceRecord != null) {
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
//...这里的代码不执行
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
//...这里的代码不执行
}
//将B的ActivityRecord加入A的ActivityRecord所在的Task里
r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
//...
} else {
//...这里的代码不执行
}
//...
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}

总结

从上面的分析可以看出来,Activity和Task的调度算法非常复杂,需结合实际场景才好分析,只有这样才知道是否需要新建Task,还是将新的ActivityRecord加入到已有的Task里,不过我们如果能理解启动模式的一些特点,对理解调度算法会有很大帮助。

大家可以结合下述场景分析调度算法:

1.从通知栏启动Activity:

假设应用有Activity A ,Activity A已启动,

此时发了一个通知,该通知用于启动Activity A,启动Activity A时不加任何特殊flag

点击通知,针对以下情况对任务调度情况进行分析:

1) Activity A的启动模式为standard

2) Activity A的启动模式为singleTop

3) Activity A的启动模式为singleTask

4) Activity A的启动模式为singleInstance

2.跨应用跳转Activity

假设应用app1有一个Activity A,另一个应用app2有一个Activity B

Activity A可跳转至Activity B

因为Activity A和Actiivty B在不同应用,所以Activity的taskffinity必然不同

现在Activity A已启动,跳转至Activity B,

针对以下4种情况分析跳转之后的Activity Task情况

1) Activity B的启动模式为standard

2) Activity B的启动模式为singleTop

3) Activity B的启动模式为singleTask

4) Activity B的启动模式为singleInstance

如果大家对上述场景分析有兴趣的话,可以在评论里一起探讨结果。

《转》深入理解Activity启动流程(四)–Activity Task的调度算法的更多相关文章

  1. 深入理解Activity启动流程(四)–Activity Task的调度算法

    本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启动的概要流程 深入理解Activity启动流程(二)- ...

  2. 《转》深入理解Activity启动流程(三)–Activity启动的详细流程2

    本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...

  3. 《转》深入理解Activity启动流程(三)–Activity启动的详细流程1

    本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...

  4. 《转》深入理解Activity启动流程(二)–Activity启动相关类的类图

    本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先为大家介绍Act ...

  5. 《转》深入理解Activity启动流程(一)–Activity启动的概要流程

    本文原创作者:Cloud Chou. 原文地址:http://www.cloudchou.com/android/post-788.html Android中启动某个Activity,将先启动Acti ...

  6. 深入理解Activity启动流程(三)–Activity启动的详细流程2

    本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--A ...

  7. 深入理解Activity启动流程(二)–Activity启动相关类的类图

    本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先 ...

  8. 深入理解Activity启动流程(一)–Activity启动的概要流程

    概述 Android中启动某个Activity,将先启动Activity所在的应用.应用启动时会启动一个以应用包名为进程名的进程,该进程有一个主线程,叫ActivityThread,也叫做UI线程. ...

  9. Android之Activity启动流程详解(基于api28)

    前言 Activity作为Android四大组件之一,他的启动绝对没有那么简单.这里涉及到了系统服务进程,启动过程细节很多,这里我只展示主体流程.activity的启动流程随着版本的更替,代码细节一直 ...

随机推荐

  1. WebStorm mac下如何安装WebStorm + 破解

    1.下载软件最好的地址就是官网了下载地址 选择好系统版本以后点击DOWNLOAD   下载Webstorm 2.安装双击下载好的安装包.将WebStromt拖入application文件夹,然后在La ...

  2. (2)R中的数据类型和数据结构

    R中的数据结构主要面向<线性代数>中的一些概念,如向量.矩阵等.值得注意的是,R中其实没有简单数据(数值型.逻辑型.字符型等),对于简单类型会自动看做长度为1的向量.比如: > b= ...

  3. python学习之路-day8

    一.接口与归一化设计 1.什么是接口 调用某个功能的方法/方式/入口 2.为什么要用接口 接口提取了一群类共同的函数,可以把接口当做一个函数的集合. 然后让子类去实现接口中的函数. 这么做的意义在于归 ...

  4. 2017中国大学生程序设计竞赛-哈尔滨站 Solution

    A - Palindrome 题意:给出一个字符串,找出其中有多少个子串满足one-half-palindromic 的定义 思路:其实就是找一个i, j  使得 以i为中轴的回文串长度和以j为中轴的 ...

  5. python webdriver api-操作富文本框

    操作富文本框-就是邮件正文部分,可以选字体啥的 第一种方式: 一般都是在iframe里,要切进去,一般是”html/body”,编辑之后,再切出来,然后再send_keys就完事儿 #encoding ...

  6. linux 常用命令总结(一)

    1. 字符串常用命令: 替换: 1). %s/*/*/g 中,替换当前界面的所有符合规则的内容.      2). 替换文件中的字符串内容: find -name '要查找的文件名' | xargs ...

  7. 前端学习笔记之CSS过渡模块

    阅读目录 一 伪类选择器复习 二 过渡模块的基本使用 三 控制过渡的速度transition-timing-function 四 过渡模块连写 一 伪类选择器复习 注意点: #1 a标签的伪类选择器可 ...

  8. Stitching模块中focalsFromHomography初步研究

    在Stitching模块中,通过“光束法平差”的时候,有一个步骤为“通过单应矩阵估算摄像头焦距”,调用的地方为:   , ));    ] ];    d2 ] ]) ] ]);    v1 ] ]  ...

  9. 期末总结20135320赵瀚青LINUX内核分析与设计期末总结

    赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 对LINUX内核分析与设计这 ...

  10. SpringMVC整个执行流程

    在SSM (或SSH) 框架整合使用后,基本骨架看上去还是MVC的结构. MyBatis整合一些数据封装方法节省了DAO层的代码量, Spring提供了AOP,IoC( DI 具体实现 ). 而Spr ...