国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

深入理解Activity啟動流程(四)–Activity Task的調度算法

2019-11-08 00:00:01
字體:
來源:轉載
供稿:網友

本系列博客將詳細闡述Activity的啟動流程,這些博客基于Cm 10.1源碼研究。

深入理解Activity啟動流程(一)--Activity啟動的概要流程深入理解Activity啟動流程(二)--Activity啟動相關類的類圖深入理解Activity啟動流程(三)--Activity啟動的詳細流程1深入理解Activity啟動流程(三)--Activity啟動的詳細流程2

前面兩篇博客介紹了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

如果大家對上述場景分析有興趣的話,可以在評論里一起探討結果。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 洛扎县| 体育| 宁夏| 论坛| 修武县| 鲁甸县| 藁城市| 安阳市| 如皋市| 宜章县| 灵璧县| 渝北区| 平乡县| 贵溪市| 连城县| 兴业县| 沐川县| 巨野县| 枣阳市| 外汇| 东城区| 封开县| 鹤山市| 酒泉市| 丹江口市| 嘉鱼县| 湖口县| 盐源县| 从江县| 保山市| 香港 | 余庆县| 内黄县| 东兰县| 新余市| 林口县| 新河县| 麻江县| 平凉市| 白城市| 丹棱县|