Android应用程序启动过程源代码分析(6)

由于在这个例子的AndroidManifest.xml文件中,MainActivity没有配置launchMode属值,因此,这里的r.launchMode为默认值0,表示以标准(Standard,或者称为ActivityInfo.LAUNCH_MULTIPLE)的方式来启动这个Activity。Activity的启动方式有四种,其余三种分别是ActivityInfo.LAUNCH_SINGLE_INSTANCE、ActivityInfo.LAUNCH_SINGLE_TASK和ActivityInfo.LAUNCH_SINGLE_TOP,具体可以参考官方网站

传进来的参数r.resultTo为null,表示Launcher不需要等这个即将要启动的MainActivity的执行结果。

由于这个intent的标志值的位Intent.FLAG_ACTIVITY_NEW_TASK被置位,而且Intent.FLAG_ACTIVITY_MULTIPLE_TASK没有置位,因此,下面的if语句会被执行:

   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 bring to front is requested, and no result is requested, and        // we can find a task that was started with this same        // component, then instead of launching bring that one to the front.        if (r.resultTo == null) {           // 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);           if (taskTop != null) {               ......           }       }      }  

这段代码的逻辑是查看一下,当前有没有Task可以用来执行这个Activity。由于r.launchMode的值不为ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task,这里返回的结果是null,即taskTop为null,因此,需要创建一个新的Task来启动这个Activity。

接着往下看:

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

这段代码的逻辑是看一下,当前在堆栈顶端的Activity是否就是即将要启动的Activity,有些情况下,如果即将要启动的Activity就在堆栈的顶端,那么,就不会重新启动这个Activity的别一个实例了,具体可以参考官方网站。现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity,因此,这里不用进一步处理上述介绍的情况。

执行到这里,我们知道,要在一个新的Task里面来启动这个Activity了,于是新创建一个Task:

  if (r.resultTo == null && !addingToTask   && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {   // todo: should do better management of integers.    mService.mCurTask++;   if (mService.mCurTask <= 0) {       mService.mCurTask = 1;   }   r.task = new TaskRecord(mService.mCurTask, r.info, intent,       (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);   ......   newTask = true;   if (mMainStack) {       mService.addRecentTaskLocked(r.task);   }         }  

新建的Task保存在r.task域中,同时,添加到mService中去,这里的mService就是ActivityManagerService了。

最后就进入startActivityLocked(r, newTask, doResume)进一步处理了。这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:

public class ActivityStack {          ......          private final void startActivityLocked(ActivityRecord r, boolean newTask,               boolean doResume) {           final int NH = mHistory.size();              int addPos = -1;              if (!newTask) {               ......           }              // Place a new activity at top of stack, so it is next to interact            // with the user.            if (addPos < 0) {               addPos = NH;           }              // If we are not placing the new activity frontmost, we do not want            // to deliver the onUserLeaving callback to the actual frontmost            // activity            if (addPos < NH) {               ......           }              // Slot the activity into the history stack and proceed            mHistory.add(addPos, r);           r.inHistory = true;           r.frontOfTask = newTask;           r.task.numActivities++;           if (NH > 0) {               // We want to show the starting preview window if we are                // switching to a new task, or the next activity's process is                // not currently running.                ......           } else {               // If this is the first activity, don't do any fancy animations,                // because there is nothing for it to animate on top of.                ......           }                      ......              if (doResume) {               resumeTopActivityLocked(null);           }       }          ......      }  

这里的NH表示当前系统中历史任务的个数,这里肯定是大于0,因为Launcher已经跑起来了。当NH>0时,并且现在要切换新任务时,要做一些任务切的界面操作,这段代码我们就不看了,这里不会影响到下面启Activity的过程,有兴趣的读取可以自己研究一下。

这里传进来的参数doResume为true,于是调用resumeTopActivityLocked进一步操作。

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

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