基于10.0的activity分析(三)

本文主要分析
从当前activity打开另一个activity(此时第一个activity设置了new_task的标记),这种情况比较简单,
从结果我们知道,这里startActivity无论如果设置了new_task的话就不会打开新的activity栈,(这里context无论是application级别的还是activity级别的都不会产生影响)
我们从ams代码里分析下
上面的就不多说了,这里还是找reusedActivity是否等于null的判断

void findTaskLocked(ActivityRecord target, FindTaskResult result) {
        Intent intent = target.intent;
        ActivityInfo info = target.info;
        ComponentName cls = intent.getComponent();
        if (info.targetActivity != null) {
            cls = new ComponentName(info.packageName, info.targetActivity);
        }
        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
        boolean isDocument = intent != null & intent.isDocument();
        // If documentData is non-null then it must match the existing task data.
        Uri documentData = isDocument ? intent.getData() : null;

        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord task = mTaskHistory.get(taskNdx);
            if (task.voiceSession != null) {
                // We never match voice sessions; those always run independently.
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
                continue;
            }
            if (task.userId != userId) {
                // Looking for a different task.
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
                continue;
            }

            // Overlays should not be considered as the task's logical top activity.
            final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
            if (r == null || r.finishing || r.mUserId != userId ||
                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
                continue;
            }
            if (!r.hasCompatibleActivityType(target)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
                continue;
            }

            final Intent taskIntent = task.intent;
            final Intent affinityIntent = task.affinityIntent;
            final boolean taskIsDocument;
            final Uri taskDocumentData;
            if (taskIntent != null && taskIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = taskIntent.getData();
            } else if (affinityIntent != null && affinityIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = affinityIntent.getData();
            } else {
                taskIsDocument = false;
                taskDocumentData = null;
            }

            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
                    + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
                    + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
            // TODO Refactor to remove duplications. Check if logic can be simplified.
            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
                    && Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                        "For Intent " + intent + " bringing to top: " + r.intent);
                result.mRecord = r;
                result.mIdealMatch = true;
                break;
            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
                    affinityIntent.getComponent().compareTo(cls) == 0 &&
                    Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                        "For Intent " + intent + " bringing to top: " + r.intent);
                result.mRecord = r;
                result.mIdealMatch = true;
                break;
            } else if (!isDocument && !taskIsDocument
                    && result.mRecord == null && task.rootAffinity != null) {
                if (task.rootAffinity.equals(target.taskAffinity)) {
                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
                    // It is possible for multiple tasks to have the same root affinity especially
                    // if they are in separate stacks. We save off this candidate, but keep looking
                    // to see if there is a better candidate.
                    result.mRecord = r;
                    result.mIdealMatch = false;
                }
            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
        }
    }

这个target就是要打开的activity,也就是testActivity
这里由于task.realActivity为MainActivity,其rootAffinity和现在的testActivity相同,但是componentName不同,所以拿到的也就是MainActivity,这里不同与第一篇的case,第一篇的case的topActivity是已经resume过的
简单来说如果设置了newTask的属性,并且历史的activityStack有相对应可以匹配的值(compentName或者是taskaffity相同)就会走这个复用的逻辑
或者是singInstance这个以后在分析
接下来调用setTargetStackAndMoveToFrontIfNeeded方法

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
        mTargetStack = intentActivity.getActivityStack();
        mTargetStack.mLastPausedActivity = null;
        // 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.
        final boolean differentTopTask;
        if (mPreferredDisplayId == mTargetStack.mDisplayId) {
            final ActivityStack focusStack = mTargetStack.getDisplay().getFocusedStack();
            final ActivityRecord curTop = (focusStack == null)
                    ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
            final TaskRecord topTask = curTop != null ? curTop.getTaskRecord() : null;
            differentTopTask = topTask != intentActivity.getTaskRecord()
                    || (focusStack != null && topTask != focusStack.topTask());
        } else {
            // The existing task should always be different from those in other displays.
            differentTopTask = true;
        }

这里判断是不是是不同的taskrecord,也就是是不是不同的activityStack
对比标准是intentActivity所在的stack和当前看到的stack做对比,很明显是相同的情况,所以所以就不会走下面条件, 接下来
看下

 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) {

setTaskFromIntentActivity方法,这里把

 else if ((mLaunchFlags & 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.
            mAddingToTask = true;
            mSourceRecord = intentActivity;
        } else if (!intentActivity.getTaskRecord().rootWasReset) {

intentActivity也就是reusedActivity赋值给了sourceActivity(这里如果是application的context是没有source的,因为它的token传过来为null,但是这里给赋值了reusedActivity作为sourceRecord),接下来就走第二篇的逻辑了,所以在当前app设置new_task没有指定taskAffinty的情况下,可以说是毫无作用

你可能感兴趣的:(基于10.0的activity分析(三))