处理启动模式的方法的是StackAcivity的代理类StackActivitySupervisor里的startActivityUncheckedLocked.
前面主要是根据Flag来判断需不需要addTask.
当New_Task_Flag时, 且instask, resultTo为null, 除了single instance都会去taskHistory去找ActivityRecord。singleInstance 例子最后再说。当找到时就会尝试着将r (这次要启动的activity)放进去,或者resumeTask里的Activity。
这里讲解下ActivityStack里的找ActivityRecord的findTaskLocked方法:
task.rootAffinity.equals(target.taskAffinity)
- 默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。所以这里用affinity作为判断条件来判别是否为想要的
taskIntent.getComponent().compareTo(cls)==0 && Objects.equals(documentData,taskDocumentData)
- 第二个匹配下 component(调用java compareTo 0为true), document若为null返回为true
affinityIntent.getComponent().compareTo(cls) ==0&&Objects.equals(documentData,taskDocumentData)
- 最后为affinityIntent的component。
当找到相对应的的record,且curTop不为找到record的task。这时用targetstack的moveTaskToFrontLocked. 在这些条件下addingtoTask为false &&reuseTask ==null
会做doResume操作。
- 当 lauchflag 为clearTop或者singleInstance或者singleTask,且能在task找到历史的activityrecord。
if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 || launchSingleInstance || launchSingleTask) {
// 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.
ActivityRecord top = intentActivity.task.performClearTaskLocked(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);
}
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent);
}
这里提一下FLAG_ACTIVITY_CLEAR_TOP这个方法。 当intent被标记上这个,会去task找相对应的ActivityRecord,找到后会清空其上的Activity然后做Resume(singleInstance和SignleTask也是如此)
- 当要启动的acitivty的reactivity (
//the intent component, or target of an alias.
) 跟task的realActivity相等时( task的realActivity为root)。 且 与task的root intent相等。
if(r.realActivity.equals(intentActivity.task.realActivity)
if (!r.intent.filterEquals(intentActivity.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 = intentActivity
}
- 上面两个没匹配到, 且lauchFlags 不为reset_task
(launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0
如果说没有做onRume操作, 后面会判断是否需要new一个新task,条件如下
if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 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.
若不new task会执行
if (sourceRecord != null) {
final TaskRecord sourceTask = sourceRecord.task;
if (isLockTaskModeViolation(sourceTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = sourceTask.stack;
targetStack.moveToFront();
final TaskRecord topTask = targetStack.topTask();
if (topTask != sourceTask) {
targetStack.moveTaskToFrontLocked(sourceTask, r, options);
} else {
mWindowManager.moveTaskToTop(topTask.taskId);
}
最后调用targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
singleTop 只会判断下顶部activity是否为想调用的如果是就resumeTop
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 || launchSingleTop || launchSingleTask) {
...
resumeTopActivitiesLocked();
...
} } } }
SingleInstance 比较特殊, 尝试去找历史Activity findActivityLocked(intent, r.info);
.
/** * Returns the first activity (starting from the top of the stack) that
* is the same as the given activity. Returns null if no such activity
* is found.
*/
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) { ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { TaskRecord task = mTaskHistory.get(taskNdx);
if (!isCurrentProfileLocked(task.userId)) {
return null;
}
final ArrayList activities = task.mActivities;
for (int activityNdx = activities.size() - 1;
activityNdx >= 0; --activityNdx) {
ActivityRecord r = activities.get(activityNdx);
if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId ==
userId) {
//Slog.i(TAG, "Found matching class!");
//dump();
//Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
return r;
}
}
}
return null;
}
另外当其它的activity尝试去用它所属的task时会直接将其过滤掉。
(r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ){
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
continue;
}
最后说下Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)这个flag. 如果intent被标记这个flag, 当task重置时它之上的activity都会被清掉。
if (clearWhenTaskReset) {
// In this case, we want to finish this activity
// and everything above it, so be sneaky and pretend
// like these are all in the reply chain.
end = numActivities - 1;
}