博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解Activity启动流程(四)–Activity Task的调度算法
阅读量:6854 次
发布时间:2019-06-26

本文共 30471 字,大约阅读时间需要 101 分钟。

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

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

startActivityUncheckedLocked方法的具体实现

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
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,任务调度执行如下所示:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
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,任务调度执行如下所示:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
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,任务调度执行如下所示:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
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里

任务调度执行如下所示:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
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

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

    本文转自 一点点征服   博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6890782.html,如需转载请自行联系原作者

你可能感兴趣的文章
华硕网络硬盘服务出问题!遭到中间人攻击
查看>>
java电子商务系统源码 Spring MVC+mybatis+spring cloud+spring boot+spring security
查看>>
Java 实现 给Excel模板赋值(直接打开表格赋值或者用自定义了名称的单元格(一块区域)赋值)...
查看>>
DataLakeAnalytics: 解析IP地址对应的国家城市地址的能力
查看>>
工程DHCP配置
查看>>
GIL(全局解释器锁)与互斥锁
查看>>
我的友情链接
查看>>
Git常用操作及分支
查看>>
关于一种求最大公约数的算法的分析与证明
查看>>
微信授权莫名创建用户数据失败的原因
查看>>
网络高手修身
查看>>
JavaWeb综合案例-键盘模拟
查看>>
Android Day03-SQLite数据库操作及ListView详解
查看>>
HTTP请求GET/POST查看工具
查看>>
php实现 坐标移动
查看>>
前端之HTML
查看>>
The Cats' Feeding Spots
查看>>
Python 进阶_OOP 面向对象编程_self 的实例绑定
查看>>
jquery内核学习(5)--对象的遍历
查看>>
在Android迷你广告上添加浮动的关闭按钮
查看>>