Android——带你从ADB命令行查看Task任务栈的管理方式

  • 一概念
    • 1Task
    • 2ActivityStack
    • 3ActivityRecordProcessRecord
  • 二任务栈的切换演示
  • 情况一单一Task默认的启动模式下App切换时的Activity栈情况
    • 1从App2ActivityB启动App1ActivityA
    • 2接着上面我们又从App1ActivityA启动App2ActivityB
  • 情况二单一Task含有SingleTask的模式App切换的Activity栈情况
    • 1从ActivityB切换至ActivityA
    • 2将MainActivity启动模式变为singleTask这时如果我们从App2ActivityB切换至App1MainActivity会发什么
  • 情况三多TaskSingleTask模式App切换时Activity栈的情况
    • 1从App2ActivatyB启动App1ActivityA
    • 2从App2ActivityB启动App1MainActivity
  • 三总结

一、概念

1、Task

Task是指将相关的Activity组合到一起,以Activity Stack的方式进行管理。从用户体验上讲,一个“应用程序”就是一个Task(默认情况),但是从根本上讲,一个Task是可以有一个或多个Android Application组成的。
Task表示一个任务,每一个Task 会有一个ID作为唯一标识。一个进程(程序)有一个默认的task affinity,默认为包名,也可以多个程序指定同一个TaskAffinity。Activity的启动会进入到对应的Task当中或者重新启动一个新的Task。Android源码里面有一个TaskRecord类,该类的一个实例就对应着一个Task。
一组Task以链表的方式相互连接,每一个Task会有一个前驱任务点和后继任务点,以此来管理Task的编辑和查找。ActivityStack外部以链表的形式管理Task,Task内部以后进先出的历史顺序方式管理Activity。
下面的Task的一段源码,我们可以看到它的主要结构:

final class TaskRecord {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
    ......
    static final String ATTR_TASKID = "task_id";
    ......
    //任务的前驱节点
    TaskRecord mPrevAffiliate; // previous task in affiliated chain.
    int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
    //该任务的后继节点
    TaskRecord mNextAffiliate; // next task in affiliated chain.
    int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
    ......

    /** List of all activities in the task arranged in history order */
    //该Task下的Activity,以后进先出的方式存放
    final ArrayList mActivities;

    /** 当前的Activity栈 */
    ActivityStack stack;
}

2、ActivityStack

Stack表示任务栈,任务栈是以Task为基本单位的。一般我们的程序切换就是Task的切换,一个程序从后台任务栈到前台任务栈,是整个任务栈的移动,而不仅仅是Activity的移动,在任务栈移动之后,再按照LaunchModel的规则对Activity进行操作。与Stack相对应的有Android源码里面的ActivityStack类。一般来说,我们的应用程序都在一个单例的ActivityStack当中。
ActivityStack里面还维护着一个Activity的LRU运行列表,按照最近访问且正在运行的Activity排列。

/**
 * 单列的Activity栈
 * State and management of a single stack of activities.
 */
final class ActivityStack {
    /**
     * List of running activities, sorted by recent usage.
     * The first entry in the list is the least recently used.
     * It contains HistoryRecord objects.
    */
    final ArrayList mLRUActivities = new ArrayList<>();

}

这个是使用adb shell dumpsys activity 查看Activity栈信息的时候打印出来的一个LRU的Activity列表。

 //LRU的方式管理的正在运行的Activity列表
 Running activities (most recent first):
   //#276表示该Task的TaskID;  A = com.example.malingyi.testtask1 表示该Task的TaskAffinity值,sz = 2表示该Task内部Activity的数量
    TaskRecord{51e812a #276 A=com.example.malingyi.testtask1 U=0 sz=2}
     Run #3: ActivityRecord{c5e365e u0 com.example.malingyi.testtask1/.ActivityA t276}
   TaskRecord{56c2a15 #277 A=com.example.malingyi.testtask2 U=0 sz=2}
     Run #2: ActivityRecord{e3bed35 u0 com.example.malingyi.testtask2/.ActivityB t277}
     Run #1: ActivityRecord{532f30e u0 com.example.malingyi.testtask2/.MainActivity t277}
   TaskRecord{51e812a #276 A=com.example.malingyi.testtask1 U=0 sz=2}
     Run #0: ActivityRecord{e5c7c57 u0 com.example.malingyi.testtask1/.MainActivity t276}


 //前台正在运行的Activity
 mResumedActivity: ActivityRecord{3a73c94 u0 com.example.malingyi.testtask2/.ActivityA t253}

3、ActivityRecord、ProcessRecord

ActivityRecord:代表着一个在Task里面正在活动的Acitivty的信息记录。

/**
 * An entry in the history stack, representing an activity.
 */
final class ActivityRecord {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
    ...

    final ActivityManagerService service; // owner
    final IApplicationToken.Stub appToken; // window manager token
    final ActivityInfo info; // all about me
    final ApplicationInfo appInfo; // information about activity's app
    final int userId;          // Which user is this running for?
    final Intent intent;    // the original intent that generated us
    final ComponentName realActivity;  // the intent component, or target of an alias.
    ...

    //包的名称
    final String packageName; // the package implementing intent's component
    //进程的名称
    final String processName; // process where this component wants to run
    //Task的名称
    final String taskAffinity; // as per ActivityInfo.taskAffinity


    //Activity所在的任务栈
    TaskRecord task;        // the task this is in.
    ...
}

ProcessRecord:当前运行的进程信息,描述了该进程的所有信息。

/**
 * Full information about a particular process that
 * is currently running.
 */
final class ProcessRecord {
    ...
}


二、任务栈的切换演示:

假设:

有两个程序:App1、App2,包名为:App1 = com.example.malingyi.testtask1 App2 = com.example.malingyi.testtask1;
ActivityA属于App1、ActivityB属于App2;两个App都有MainActivity作为启动入口。

情况一:单一Task&默认的启动模式下,App切换时的Activity栈情况

启动模式:

ActivityA:standard
ActivityB:standard
App1、App2:MainActivity:standard

TaskAffinity:

都是默认情况下的TaskAffinity(包名)

初始化启动顺序:

Step1:启动App1:MainActivity——>ActivityA ;
Step2:启动App2:MainActivity——>ActivityB;

**栈顶Activity:**ActivityB

Activity栈:

App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB

初始任务栈信息如下:

Stack #8:
    Task id #282 //App2的Task栈
      TaskRecord{cde1503 #282 A=com.example.malingyi.testtask2 U=0 sz=2}  //Task信息
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
        Hist #1: ActivityRecord{218b549 u0 com.example.malingyi.testtask2/.ActivityB t282}//Activity信息
          Intent { cmp=com.example.malingyi.testtask2/.ActivityB }
          ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}
        Hist #0: ActivityRecord{735919e u0 com.example.malingyi.testtask2/.MainActivity t282}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
          ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63} //进程信息
    Task id #281。//App1的Task栈
      TaskRecord{8480c80 #281 A=com.example.malingyi.testtask1 U=0 sz=2}  //Task信息
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
        Hist #1: ActivityRecord{66d10ee u0 com.example.malingyi.testtask1/.ActivityA t281}//Activity信息
          Intent { cmp=com.example.malingyi.testtask1/.ActivityA }
          ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}
        Hist #0: ActivityRecord{157ed43 u0 com.example.malingyi.testtask1/.MainActivity t281}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
          ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60} //进程信息

(1)从App2.ActivityB启动App1.ActivityA

切换后任务栈:

Stack #8:
   Task id #282  //栈顶还是App2的Task,APP.ActivityA进入了App2的Task栈中。
     TaskRecord{cde1503 #282 A=com.example.malingyi.testtask2 U=0 sz=3}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
       Hist #2: ActivityRecord{c6170ac u0 com.example.malingyi.testtask1/.ActivityA t282}
         Intent { act=com.exaple.malingyi.ActivityA cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}
       Hist #1: ActivityRecord{218b549 u0 com.example.malingyi.testtask2/.ActivityB t282}
         Intent { cmp=com.example.malingyi.testtask2/.ActivityB }
         ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}
       Hist #0: ActivityRecord{735919e u0 com.example.malingyi.testtask2/.MainActivity t282}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
         ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}

   Task id #281
     TaskRecord{8480c80 #281 A=com.example.malingyi.testtask1 U=0 sz=2}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
       Hist #1: ActivityRecord{66d10ee u0 com.example.malingyi.testtask1/.ActivityA t281}
         Intent { cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}
       Hist #0: ActivityRecord{157ed43 u0 com.example.malingyi.testtask1/.MainActivity t281}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}

初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB
操作后的栈:App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB——>App1.ActivityA

这里我们看到,App1.ActivityA重新创建了一个实例进入了App2的Task栈。

(2)接着上面,我们又从App1.ActivityA启动App2.ActivityB

任务栈信息:

Task id #282   //栈顶仍然是App2的Task,APP2.ActivityB进入了App2的Task栈中。
     TaskRecord{cde1503 #282 A=com.example.malingyi.testtask2 U=0 sz=4}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
       Hist #3: ActivityRecord{6e68c29 u0 com.example.malingyi.testtask2/.ActivityB t282}
         Intent { act=com.exaple.malingyi.ActivityB cmp=com.example.malingyi.testtask2/.ActivityB }
         ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}
       Hist #2: ActivityRecord{c6170ac u0 com.example.malingyi.testtask1/.ActivityA t282}
         Intent { act=com.exaple.malingyi.ActivityA cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}
       Hist #1: ActivityRecord{218b549 u0 com.example.malingyi.testtask2/.ActivityB t282}
         Intent { cmp=com.example.malingyi.testtask2/.ActivityB }
         ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}
       Hist #0: ActivityRecord{735919e u0 com.example.malingyi.testtask2/.MainActivity t282}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
         ProcessRecord{77bd789 3202:com.example.malingyi.testtask2/u0a63}

   Task id #281
     TaskRecord{8480c80 #281 A=com.example.malingyi.testtask1 U=0 sz=2}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
       Hist #1: ActivityRecord{66d10ee u0 com.example.malingyi.testtask1/.ActivityA t281}
         Intent { cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}
       Hist #0: ActivityRecord{157ed43 u0 com.example.malingyi.testtask1/.MainActivity t281}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
         ProcessRecord{57c82b9 3305:com.example.malingyi.testtask1/u0a60}

初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB
操作后的栈:App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB——>App1.ActivityA——>App2.ActivityB

同样,我们看到新启动的ActivityB,还是在原有的App2的Task栈中。
这里的到了两个结论:

  • standard模式下,Activity会重新创建一个新的实例,不论原有实例是否存在。
  • standard模式下,Activity会进入启动它的Activity所在的Task栈中,这个结论对于在启动其他App的Activity也成立。

情况二:单一Task&含有SingleTask的模式,App切换的Activity栈情况

启动模式:

ActivityA:SingleTask
ActivityB:SingleTask
App1、App2:MainActivity:standard

TaskAffinity:

都是默认情况下的TaskAffinity(包名)

初始化启动顺序:

Step1:启动App1:MainActivity——>ActivityA ;
Step2:启动App2:MainActivity——>ActivityB;

栈顶Activity:ActivityB

Activity栈:

App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB

初始任务栈:

//所有启动的Activity,按照Task来分组,按照任务的访问顺序从上到下的排列。

Display #0 (activities from top to bottom):
  Stack #7:
    Task id #277   //App2的Task,里面维护了Activity的入栈顺序
      TaskRecord{56c2a15 #277 A=com.example.malingyi.testtask2 U=0 sz=2}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
        Hist #1: ActivityRecord{e3bed35 u0 com.example.malingyi.testtask2/.ActivityB t277}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
          ProcessRecord{9d3fb1b 2959:com.example.malingyi.testtask2/u0a63}
        Hist #0: ActivityRecord{532f30e u0 com.example.malingyi.testtask2/.MainActivity t277}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
          ProcessRecord{9d3fb1b 2959:com.example.malingyi.testtask2/u0a63} //标明Task所属的进程

    Task id #276。 //App1的Task,里面维护了Activity的入栈顺序
      TaskRecord{51e812a #276 A=com.example.malingyi.testtask1 U=0 sz=2}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.malingyi.testtask1/.MainActivity }
        Hist #1: ActivityRecord{c5e365e u0 com.example.malingyi.testtask1/.ActivityA t276}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
          ProcessRecord{7a654b8 2877:com.example.malingyi.testtask1/u0a60}
        Hist #0: ActivityRecord{e5c7c57 u0 com.example.malingyi.testtask1/.MainActivity t276}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.malingyi.testtask1/.MainActivity }
          ProcessRecord{7a654b8 2877:com.example.malingyi.testtask1/u0a60}  //标明Task所属的进程


    //正在运行的是App2的ActivityB
    mResumedActivity: ActivityRecord{bf1f68 u0 com.example.malingyi.testtask1/com.example.malingyi.testtask2.ActivityB t272}

(1)从ActivityB切换至ActivityA:

切换后任务栈:

Stack #7:
   Task id #276 //App1的整个栈上移了!不止是Activity移到了前面,同时在Task下的MainActivity也一起移动了。
     TaskRecord{51e812a #276 A=com.example.malingyi.testtask1 U=0 sz=2}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.malingyi.testtask1/.MainActivity }
       Hist #1: ActivityRecord{c5e365e u0 com.example.malingyi.testtask1/.ActivityA t276}
         Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{7a654b8 2877:com.example.malingyi.testtask1/u0a60}
       Hist #0: ActivityRecord{e5c7c57 u0 com.example.malingyi.testtask1/.MainActivity t276}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.malingyi.testtask1/.MainActivity }
         ProcessRecord{7a654b8 2877:com.example.malingyi.testtask1/u0a60}
   Task id #277 //App2的栈下调了
     TaskRecord{56c2a15 #277 A=com.example.malingyi.testtask2 U=0 sz=2}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
       Hist #1: ActivityRecord{e3bed35 u0 com.example.malingyi.testtask2/.ActivityB t277}
         Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
         ProcessRecord{9d3fb1b 2959:com.example.malingyi.testtask2/u0a63}
       Hist #0: ActivityRecord{532f30e u0 com.example.malingyi.testtask2/.MainActivity t277}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
         ProcessRecord{9d3fb1b 2959:com.example.malingyi.testtask2/u0a63}

         初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB
         操作后的栈:App2.ActivityB——>App1.ActivityA——>App1.MainActivity——>App1.ActivityA

原本只是从ActivityA切换到ActivityB,由于ActivityB是SingleTask同时实例已经存在,那么应该是ActivityB移动到ActivityA之前,但是MainActivity也同时移到了ActivityA之前。MainActivity与ActivityA整个Task栈都移动了。按照Task的定义,ActivityStack栈里是按照Task分组来管理Activity,那么有可能APP之间的切换的调度单位会是Task。

(2)将MainActivity启动模式变为:singleTask。这时如果我们从App2.ActivityB切换至App1.MainActivity会发什么?

切换后任务栈:

Stack #10:
  Task id #289  //App1的Task栈移动到了App2的Task栈之前,但是这时情况是MainActivity之前的App1.ActivityA弹出了。Task栈下只剩MainActivity
    TaskRecord{fd59417 #289 A=com.example.malingyi.testtask1 U=0 sz=1}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
      Hist #0: ActivityRecord{24d5faa u0 com.example.malingyi.testtask1/.MainActivity t289}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
        ProcessRecord{219a9ed 3807:com.example.malingyi.testtask1/u0a60}
  Task id #290
    TaskRecord{1d94004 #290 A=com.example.malingyi.testtask2 U=0 sz=2}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
      Hist #1: ActivityRecord{dd07174 u0 com.example.malingyi.testtask2/.ActivityB t290}
        Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
        ProcessRecord{101c022 3830:com.example.malingyi.testtask2/u0a63}
      Hist #0: ActivityRecord{2c3fdf1 u0 com.example.malingyi.testtask2/.MainActivity t290}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
        ProcessRecord{101c022 3830:com.example.malingyi.testtask2/u0a63}

初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB
操作后的栈:App2.ActivityB——>App1.ActivityA——>App1.MainActivity

MainActivity为SingleTask之后,由于它已经存在了一个实例,因此切换的时候会把App1的Task移动到App2的Task之前。然后根据SingleTask的规则,会将Task内在它之前的的Activity弹出,使得它置顶。

到了这里,我们可以得出一个结论:

  • APP切换时,首先,会将切换的App所在的Task移动到最前面;然后,再使用LaunchModel的规则对Activity进行出栈入栈的操作。

然后再作出一个假设:

  • 我们在两个程序之间的切换可能就是Task的切换?

情况三:多Task&SingleTask模式,App切换时Activity栈的情况

启动模式&TaskAffinity:

App1、App2的MainActivity的LaunchModel = SingleTask, TaskAffinity = 包名;
App1中ActivityA: LaunchModel = SingleTask, TaskAffinity = com.TaskA;
App2中ActivityB: LaunchModel = SingleTask, TaskAffinity = com.TaskB;

初始化启动顺序:

Step1:启动App1:MainActivity——>ActivityA ;
Step2:启动App2:MainActivity——>ActivityB;

栈顶Activity:ActivityB

初始Activity栈:

App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB

初始任务栈:

//我们可以看到,每一个Activity都在一个Task中,按照他们启动的顺序从上倒下。
  Stack #11:
    Task id #296 //App2.ActivityB的任务栈com.TaskB
      TaskRecord{85070a0 #296 A=com.TaskB U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
        Hist #0: ActivityRecord{8c75fd1 u0 com.example.malingyi.testtask2/.ActivityB t296}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
          ProcessRecord{f5bf6cc 4090:com.example.malingyi.testtask2/u0a63}

    Task id #295 //App2.MainActivity的任务栈com.example.malingyi.testtask2
      TaskRecord{850e459 #295 A=com.example.malingyi.testtask2 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
        Hist #0: ActivityRecord{52f95ba u0 com.example.malingyi.testtask2/.MainActivity t295}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
          ProcessRecord{f5bf6cc 4090:com.example.malingyi.testtask2/u0a63}
    Task id #294  //App1.ActivityA的任务栈
      TaskRecord{5da881e #294 A=com.TaskA U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
        Hist #0: ActivityRecord{43ed667 u0 com.example.malingyi.testtask1/.ActivityA t294}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
          ProcessRecord{d226d15 4068:com.example.malingyi.testtask1/u0a60}
    Task id #293   //App1.MainActivity的任务栈
      TaskRecord{8b948ff #293 A=com.example.malingyi.testtask1 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
        Hist #0: ActivityRecord{7669776 u0 com.example.malingyi.testtask1/.MainActivity t293}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
          ProcessRecord{d226d15 4068:com.example.malingyi.testtask1/u0a60}

    //正在最前台的Activity
    mResumedActivity: ActivityRecord{8c75fd1 u0 com.example.malingyi.testtask2/.ActivityB t296}

从上面的结果可以看出,由于给ActivityA、ActivityB指定了TaskAffinity、SingleTask,两个MainActivity跟随App默认的任务栈,因此每一个Activity都有一个Task任务栈。但还是会按照进程将他们分为两个APP。

注意看ProcessRecord字段会发现,App1.ActivityA和App1.MainActivity1是属于同一个Process(d226d15 4068:com.example.malingyi.testtask1/u0a60)。而App2.ActivityB和App2.MainActivity2是属于另一个
Process(f5bf6cc 4090:com.example.malingyi.testtask2/u0a6)。

(1)从App2.ActivatyB启动App1.ActivityA

切换任务栈:

Stack #11:
    Task id #294 //App1.ActivityA所在的任务栈移到了最前面
      TaskRecord{5da881e #294 A=com.TaskA U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
        Hist #0: ActivityRecord{43ed667 u0 com.example.malingyi.testtask1/.ActivityA t294}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
          ProcessRecord{d226d15 4068:com.example.malingyi.testtask1/u0a60}
    Task id #296 //App2.ActivityB所在的任务栈
      TaskRecord{85070a0 #296 A=com.TaskB U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
        Hist #0: ActivityRecord{8c75fd1 u0 com.example.malingyi.testtask2/.ActivityB t296}
          Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
          ProcessRecord{f5bf6cc 4090:com.example.malingyi.testtask2/u0a63}
    Task id #295 //App2.MainActivity所在的任务栈
      TaskRecord{850e459 #295 A=com.example.malingyi.testtask2 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
        Hist #0: ActivityRecord{52f95ba u0 com.example.malingyi.testtask2/.MainActivity t295}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
          ProcessRecord{f5bf6cc 4090:com.example.malingyi.testtask2/u0a63}
    Task id #293 //App1.MainActivity所在的任务栈
      TaskRecord{8b948ff #293 A=com.example.malingyi.testtask1 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
        Hist #0: ActivityRecord{7669776 u0 com.example.malingyi.testtask1/.MainActivity t293}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
          ProcessRecord{d226d15 4068:com.example.malingyi.testtask1/u0a60}

    Running activities (most recent first):
      TaskRecord{5da881e #294 A=com.TaskA U=0 sz=1}
        Run #3: ActivityRecord{43ed667 u0 com.example.malingyi.testtask1/.ActivityA t294}
      TaskRecord{85070a0 #296 A=com.TaskB U=0 sz=1}
        Run #2: ActivityRecord{8c75fd1 u0 com.example.malingyi.testtask2/.ActivityB t296}
      TaskRecord{850e459 #295 A=com.example.malingyi.testtask2 U=0 sz=1}
        Run #1: ActivityRecord{52f95ba u0 com.example.malingyi.testtask2/.MainActivity t295}
      TaskRecord{8b948ff #293 A=com.example.malingyi.testtask1 U=0 sz=1}
        Run #0: ActivityRecord{7669776 u0 com.example.malingyi.testtask1/.MainActivity t293}

    mResumedActivity: ActivityRecord{43ed667 u0 com.example.malingyi.testtask1/.ActivityA t294}

这里我们看到,只有Task#294(App1.ActivityA)移动到了Task#296(App2.ActivityB)之前,App1.MainActivity所在的Task#293,并没有移动。

初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB
操作后的栈:App1.MainActivity——>App2.MainActivity——>App2.ActivityB——>App1.ActivityA

(2)从App2.ActivityB启动App1.MainActivity

切换任务栈:

Stack #12:
   Task id #297  //App1.MainActivity所在的任务栈移到了最前面
     TaskRecord{6b63e70 #297 A=com.example.malingyi.testtask1 U=0 sz=1}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
       Hist #0: ActivityRecord{f87eb51 u0 com.example.malingyi.testtask1/.MainActivity t297}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask1/.MainActivity bnds=[60,972][180,1092] (has extras) }
         ProcessRecord{818d19c 4795:com.example.malingyi.testtask1/u0a60}
   Task id #300  //App2.ActivityB所在的任务栈
     TaskRecord{d3ee5e9 #300 A=com.TaskB U=0 sz=1}
     Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
       Hist #0: ActivityRecord{3df6276 u0 com.example.malingyi.testtask2/.ActivityB t300}
         Intent { flg=0x10000000 cmp=com.example.malingyi.testtask2/.ActivityB }
         ProcessRecord{d16f7a5 4819:com.example.malingyi.testtask2/u0a63}
   Task id #299  //App2.MainActivity所在的任务栈
     TaskRecord{90b126e #299 A=com.example.malingyi.testtask2 U=0 sz=1}
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
       Hist #0: ActivityRecord{9778bab u0 com.example.malingyi.testtask2/.MainActivity t299}
         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.malingyi.testtask2/.MainActivity bnds=[236,972][356,1092] (has extras) }
         ProcessRecord{d16f7a5 4819:com.example.malingyi.testtask2/u0a63}
   Task id #298  //App1.ActivityA所在的任务栈
     TaskRecord{8688d0f #298 A=com.TaskA U=0 sz=1}
     Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
       Hist #0: ActivityRecord{f78be54 u0 com.example.malingyi.testtask1/.ActivityA t298}
         Intent { flg=0x10000000 cmp=com.example.malingyi.testtask1/.ActivityA }
         ProcessRecord{818d19c 4795:com.example.malingyi.testtask1/u0a60}

我重新启动了一次APP,因此Task#ID改变了,但是他们初始的启动顺序没变。

初始栈: App1.MainActivity——>App1.ActivityA——>App2.MainActivity——>App2.ActivityB。
操作后的栈:App1.ActivityA——>App2.MainActivity——>App2.ActivityB——>App1.MainActivity

我们仍然看到,只有Task#297 (App1.MainActivity)移动到了Task#300(App2.ActivityB)之前,App1.ActivityA所在的Task#298。

到了这里,假设已经得到了实践的验证:

  • Android的APP切换,实际上是Activity以Task为单位来进行切换,将被选中的Activity所在的Task移动到Stack任务栈的最前端,然后在Task内部使用LaunchModel规则对Task内部的Activity进行操作。

三、总结

  • standard模式下,Activity会进入启动它的Activity所在的Task栈中,这个结论对于在启动其他App的Activity也成立。

  • LaunchModel的启动规则,在跨App之间时启动Activity同样成立。

  • 在APP之间切换时。首先,会将切换的App所在的Task移动到最前面;然后,再使用LaunchModel的规则对Activity进行出栈入栈的操作。

  • Android的APP切换,实际上是以Task为单位来进行切换,将被选中的Activity所在的Task移动到Stack任务栈的最前端,然后在Task内部根据Activity的启动模式,使用LaunchModel规则对Task内部的Activity进行操作。

你可能感兴趣的:(Android,Coding,编程体会,Android开发)