處理啟動模式的方法的是StackAcivity的代理類StackActivitySupervisor里的startActivityUncheckedLocked.
前面主要是根據(jù)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會執(zhí)行
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<ActivityRecord> 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;
}