解开Android应用程序组件Activity的“singleTask”之谜(4)

这个函数无非就是根据即将要启动的SubActivity的taskAffinity属性值在系统中查找这样的一个Task:Task的affinity属性值与即将要启动的Activity的taskAffinity属性值一致。如果存在,就返回这个Task堆栈顶端的Activity回去。在上面的AndroidManifest.xml文件中,没有配置MainActivity和SubActivity的taskAffinity属性,于是它们的taskAffinity属性值就默认为父标签application的taskAffinity属性值,这里,标签application的taskAffinity也没有配置,于是它们就默认为包名,即"shy.luo.task"。由于在启动SubActivity之前,MainActivity已经启动,MainActivity启动的时候,会在一个新的任务里面启动,而这个新的任务的affinity属性就等于它的第一个Activity的taskAffinity属性值。于是,这个函数会动回表示MainActivity的ActivityRecord回去.

回到前面的startActivityUncheckedLocked函数中,这里的taskTop就表示MainActivity,它不为null,于是继续往前执行。由于条件r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK成立,于是执行下面语句:

ActivityRecord top = performClearTaskLocked(   kTop.task.taskId, r, launchFlags, true);  

        函数performClearTaskLocked也是定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:

 

public class ActivityStack {          ......          /**      * Perform clear operation as requested by      * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the      * stack to the given task, then look for      * an instance of that activity in the stack and, if found, finish all      * activities on top of it and return the instance.      *      * @param newR Description of the new activity being started.      * @return Returns the old activity that should be continue to be used,      * or null if none was found.      */       private final ActivityRecord performClearTaskLocked(int taskId,       ActivityRecord newR, int launchFlags, boolean doClear) {           int i = mHistory.size();              // First find the requested task.            while (i > 0) {               i--;               ActivityRecord r = (ActivityRecord)mHistory.get(i);               if (r.task.taskId == taskId) {                   i++;                   break;               }           }              // Now clear it.            while (i > 0) {               i--;               ActivityRecord r = (ActivityRecord)mHistory.get(i);               if (r.finishing) {                   continue;               }               if (r.task.taskId != taskId) {                   return null;               }               if (r.realActivity.equals(newR.realActivity)) {                   // Here it is!  Now finish everything in front...                    ActivityRecord ret = r;                   if (doClear) {                       while (i < (mHistory.size()-1)) {                           i++;                           r = (ActivityRecord)mHistory.get(i);                           if (r.finishing) {                               continue;                           }                           if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,                               null"clear")) {                                   i--;                           }                       }                   }                      // Finally, if this is a normal launch mode (that is, not                    // expecting onNewIntent()), then we will finish the current                    // instance of the activity so a new fresh one can be started.                    if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE                       && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {                           if (!ret.finishing) {                               int index = indexOfTokenLocked(ret);                               if (index >= 0) {                                   finishActivityLocked(ret, index, Activity.RESULT_CANCELED,                                       null"clear");                               }                               return null;                           }                   }                      return ret;               }           }              return null;       }          ......      }  

        这个函数中作用无非就是找到ID等于参数taskId的任务,然后在这个任务中查找是否已经存在即将要启动的Activity的实例,如果存在,就会把这个Actvity实例上面直到任务堆栈顶端的Activity通过调用finishActivityLocked函数将它们结束掉。在这个例子中,就是要在属性值affinity等于"shy.luo.task"的任务中看看是否存在SubActivity类型的实例,如果有,就把它上面的Activity都结束掉。这里,属性值affinity等于"shy.luo.task"的任务只有一个MainActivity,而且它不是SubActivity的实例,所以这个函数就返回null了。

回到前面的startActivityUncheckedLocked函数中,这里的变量top就为null了,于是执行下面的else语句:

   if (top != null) {   ......      } 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;      }  

        于是,变量addingToTask值就为true了,同时将变量sourceRecord的值设置为taskTop,即前面调用findTaskLocked函数的返回值,这里,它就是表示MainActivity了。

继续往下看,下面这个if语句:

   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)) {               if (top.app != null && top.app.thread != null) {               ......           }       }   }         } else {   ......      }  

        它是例行性地检查当前任务顶端的Activity,是否是即将启动的Activity的实例,如果是否的话,在某些情况下,它什么也不做,就结束这个函数调用了。这里,当前任务顶端的Activity为MainActivity,它不是SubActivity实例,于是继续往下执行:

   boolean newTask = false;         // Should this be considered a new task?       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) {       ......   }   // 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.    r.task = sourceRecord.task;             ......         } else {          ......      }  

        这里首先将newTask变量初始化为false,表示不要在新的任务中启动这个SubActivity。由于前面的已经把addingToTask设置为true,因此,这里会执行中间的else if语句,即这里会把r.task设置为sourceRecord.task,即把SubActivity放在MainActivity所在的任务中启动。

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwgxdw.html