美文网首页
基于10.0的activity分析(三)

基于10.0的activity分析(三)

作者: 暴走的小青春 | 来源:发表于2020-07-24 13:39 被阅读0次

    本文主要分析
    从当前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分析(三)

          本文链接:https://www.haomeiwen.com/subject/zpxjlktx.html