Android应用程序组件Activity的"singleTask"(6)

移动开发 Android
现在,我们如何来确认SubActivity是不是在新的任务中启动并且位于这个新任务的堆栈底部呢?Android源代码工程为我们准备了adb工具,可以查看模拟器上系统运行的状况。

现在,我们如何来确认SubActivity是不是在新的任务中启动并且位于这个新任务的堆栈底部呢?

Android源代码工程为我们准备了adb工具。

可以查看模拟器上系统运行的状况。

执行下面的命令查看:

  1. [html] view plaincopyUSER-NAME@MACHINE-NAME:~/Android$ adb shell dumpsys 
  2. tivity 
  3. 这个命令输出的内容比较多,这里我们只关心TaskRecord部分:[html] view plaincopyRunning activities 
  4. ost recent first): 
  5. TaskRecord{4070d8f8 #3 A shy.luo.task} 
  6. Run #2: HistoryRecord{406a13f8 shy.luo.task/.SubActivity} 
  7. Run #1: HistoryRecord{406a0e00 shy.luo.task/.MainActivity} 
  8. TaskRecord{4067a510 #2 A com.android.launcher} 
  9. Run #0: HistoryRecord{40677518 
  10. m.android.launcher/com.android.launcher2.Launcher} 

果然,SubActivity和MainActivity都是运行在TaskRecord#3中,并且SubActivity在MainActivity 的上面。这是怎么回事呢?碰到这种情况,Linus Torvalds告诫我们:Read the fucking source code;去年张麻子又说:枪在手,跟我走;我们没有枪,但是有source code,因此,我要说:跟着代码走。

前面我们在两篇文章Android应用程序启动过程源代码分析和Android应用程序内部启动Activity过程(startActivity) 的源代码分析时,分别在Step 9和Step 8中分析了Activity在启动过程中与任务相关的函数ActivityStack.startActivityUncheckedLocked函数 中,它定义在frameworks/base/services/java/com/android/server/am /ActivityStack.java文件中:

  1.   [java] view plaincopypublic class ActivityStack { 
  2.   ...... 
  3.   final int startActivityUncheckedLocked(ActivityRecord r, 
  4.   ActivityRecord sourceRecord, Uri[] grantedUriPermissions, 
  5.   int grantedMode, boolean onlyIfNeeded, boolean doResume) { 
  6.   final Intent intent = r.intent; 
  7.   final int callingUid = r.launchedFromUid; 
  8.   int launchFlags = intent.getFlags(); 
  9.   ...... 
  10.   ActivityRecord notTop = 
  11. (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) 
  12.   != 0 ? r : null
  13.   ...... 
  14.   if (sourceRecord == null) { 
  15.   ...... 
  16.   } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) 
  17.   ...... 
  18.   } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE 
  19.   || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 
  20.   // The activity being started is a single instance... it always 
  21.   // gets launched into its own task. 
  22.   launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 
  23.   } 
  24.   ...... 
  25.   boolean addingToTask = false
  26.   if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 
  27.   (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0
  28.   || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 
  29.   || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 
  30.   // If bring to front is requested, and no result is requested, and 
  31.   // we can find a task that was started with this same 
  32.   // component, then instead of launching bring that one to the front. 
  33.   if (r.resultTo == null) { 
  34.   // See if there is a task to bring to the front. If this is 
  35.   // a SINGLE_INSTANCE activity, there can be one and only one 
  36.   // instance of it in the history, and it is always in its own 
  37.   // unique task, so we do a special search. 
  38.   ActivityRecord taskTop = r.launchMode != 
  39. ActivityInfo.LAUNCH_SINGLE_INSTANCE 
  40.   ? findTaskLocked(intent, r.info) 
  41.   : findActivityLocked(intent, r.info); 
  42.   if (taskTop != null) { 
  43.   ...... 
  44.   if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 
  45.   || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 
  46.   || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 
  47.   // In this situation we want to remove all activities 
  48.   // from the task up to the one being started. In most 
  49.   // cases this means we are resetting the task to its 
  50.   // initial state. 
  51.   ActivityRecord top = performClearTaskLocked( 
  52.   taskTop.task.taskId, r, launchFlags, true); 
  53.   if (top != null) { 
  54.   ...... 
  55.   } else { 
  56.   // A special case: we need to 
  57.   // start the activity because it is not currently 
  58.   // running, and the caller has asked to clear the 
  59.   // current task to have this activity at the top. 
  60.   addingToTask = true
  61.   // Now pretend like this activity is being started 
  62.   // by the top of its task, so it is put in the 
  63.   // right place. 
  64.   sourceRecord = taskTop; 
  65.   } 
  66.   } else if (r.realActivity.equals(taskTop.task.realActivity)) { 
  67.   ...... 
  68.   } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 
  69. 0) { 
  70.   ...... 
  71.   } else if (!taskTop.task.rootWasReset) { 
  72.   ...... 
  73.   } 
  74.   ...... 
  75.   } 
  76.   } 
  77.   } 
  78.   ...... 
  79.   if (r.packageName != null) { 
  80.   // If the activity being launched is the same as the one currently 
  81.   // at the top, then we need to check if it should only be launched 
  82.   // once. 
  83.   ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); 
  84.   if (top != null && r.resultTo == null) { 
  85.   if (top.realActivity.equals(r.realActivity)) { 
  86.   if (top.app != null && top.app.thread != null) { 
  87.   ...... 
  88.   } 
  89.   } 
  90.   } 
  91.   } else { 
  92.   ...... 
  93.   } 
  94.   boolean newTask = false
  95.   // Should this be considered a new task? 
  96.   if (r.resultTo == null && !addingToTask 
  97.   && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 
  98.   // todo: should do better management of integers. 
  99.   mService.mCurTask++; 
  100.   if (mService.mCurTask <= 0) { 
  101.   mService.mCurTask = 1
  102.   } 
  103.   r.task = new TaskRecord(mService.mCurTask, r.info, intent, 
  104.   (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0); 
  105.   if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 
  106.   + " in new task " + r.task); 
  107.   newTask = true
  108.   if (mMainStack) { 
  109.   mService.addRecentTaskLocked(r.task); 
  110.   } 
  111.   } else if (sourceRecord != null) { 
  112.   if (!addingToTask && 
  113.   (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 
  114.   ...... 
  115.   } else if (!addingToTask && 
  116.   (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { 
  117.   ...... 
  118.   } 
  119.   // An existing activity is starting this new activity, so we want 
  120.   // to keep the new one in the same task as the one that is starting 
  121.   // it. 
  122.   r.task = sourceRecord.task; 
  123.   ...... 
  124.   } else { 
  125.   ...... 
  126.   } 
  127.   ...... 
  128.   startActivityLocked(r, newTask, doResume); 
  129.   return START_SUCCESS; 
  130.   } 
  131.   ...... 
  132.   } 

 

责任编辑:闫佳明 来源: bbs.9ria
相关推荐

2014-05-27 14:12:49

AndroidActivitysingleTask

2014-05-27 15:07:07

AndroidActivitysingleTask

2014-05-27 14:16:08

AndroidActivitysingleTask

2014-05-27 14:09:52

AndroidActivitysingleTask

2014-05-27 15:17:46

AndroidActivitysingleTask

2014-05-27 14:28:25

AndroidActivitysingleTask

2014-05-27 15:11:20

AndroidActivitysingleTask

2014-05-27 15:09:13

AndroidActivitysingleTask

2014-05-27 15:04:15

AndroidActivitysingleTask

2014-05-27 14:33:37

AndroidActivitysingleTask

2014-05-27 14:59:24

AndroidActivitysingleTask

2010-02-06 15:26:11

Android应用程序

2009-08-14 17:08:00

Android应用程序

2013-01-17 15:51:42

Android开发应用程序组件

2020-09-04 14:56:23

应用程序疫情

2010-11-11 14:38:37

2022-09-27 15:16:42

开发Android应用程序

2014-05-22 15:18:25

Android消息处理机制Looper

2011-05-24 16:09:57

Androi

2010-03-03 16:45:46

Android应用程序
点赞
收藏

51CTO技术栈公众号