ActivityRecord、TaskRecord、ActivityStack、ActivityDisplay、ActivityStackSupervisor到底是干嘛的?

  最近在阅读Activity启动过程时接触到了这几个概念:ActivityRecord、TaskRecord、ActivityStack、ActivityDisplay、ActivityStackSupervisor。它们是什么?可以用来干什么?以及怎么干的?网络上,常见的回答就是ActivityStackSupervisor管理ActivityDisplay,ActivityDisplay管理ActivityStack、ActivityStack管理TaskRecord、TaskRecord管理ActivityRecord。但是到底怎么管理的?为什么要管理啊?哎,没讲明白~~。
  今天就由我来介绍下这几个概念。

ActivityRecord

  ActivityRecord是Activity在system_server进程中的镜像,Activity实例与ActivityRecord实例一一对应。ActivityRecord用来存储Activity的信息,如所在的进程名称,应用的包名,所在的任务栈的taskAffinity等。

/**
 * An entry in the history stack, representing an activity.
 */
final class ActivityRecord {
	final ComponentName realActivity;  // the intent component, or target of an alias.
    final String shortComponentName; // the short component name of the intent
    final String packageName; // the package implementing intent's component
    final String processName; // process where this component wants to run
    final String taskAffinity; // as per ActivityInfo.taskAffinity
    boolean fullscreen; // covers the full screen?
}

TaskRecord

  TaskRecord表示任务栈,用于记录activity开启的先后顺序。其所存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。有了TaskRecord,Android系统才能知道当一个Activity退出时,接下来该显示哪一个Activity。

final class TaskRecord {
	/** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities;
}

ActivityStack

  ActivityStack这个类在名字上给人很大的误解,Stack是栈的意思(Heap是堆的意思),那ActivityStack就表示“Activity的栈”?其实不是。从下面的代码中可以看出ActivityStack维护的是TaskRecord的列表。而且该列表也不是栈结构,列表中的TaskRecord可以重排顺序。

final class ActivityStack {
	/**
     * The back history of all previous (and possibly still
     * running) activities.  It contains #TaskRecord objects.
     */
    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
}

  也有人说是一个APP对应一个ActivityStack。其实也不是。
  接下来就用命令行——adb shell dumpsys activity,来验证以下2个问题:

   1. ActivityStack维护的TaskRecord列表是否可以重排顺序
   2. APP与ActivityStack的关系

  先准备2个APP。app1和app2各自都有两个页面,各自的启动页都是普通常见的,然后各自的都有另外一个其他页面,这分属于两个app的其他页面我们都给他们指定同一个任务栈名(这个任务栈名不跟任意一个app包名相同)。
  也就是说app1里面有MainActivity和OtherActivity1。app2里面有MainActivity和OtherActivity2。两个应用的MainActivity都是普通的Standard启动模式,而OtherActivity1和OtherActivity2都在清单文件指定了同一个自定义的任务栈名称和singelTask启动模式。
  我们这样操作:
  第一阶段:先打开app1,再打开OtherActivity1页面。
  第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
  先贴上相关图片和代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
app1的manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.a_task.application">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.a_task.application.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.a_task.application.OtherActivity1"
            android:launchMode="singleTask"
            android:taskAffinity="com.task.other.independent"/>
        <activity android:name="com.a_task.application.StandActivity" />
    </application>

</manifest>

app2的manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.b_task.application2">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.b_task.application2.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.b_task.application2.OtherActivity2"
            android:launchMode="singleTask"
            android:taskAffinity="com.task.other.independent"/>
    </application>

</manifest>
  • 第一阶段:先打开app1,再打开OtherActivity1页面。
    在cmd窗口中输入adb shell dumpsys activity。查看任务栈信息。搜索ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)部分的内容。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)

Display #0 (activities from top to bottom):

  Stack #1:

    Task id #3

      TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=1}
        Hist #0: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}

    Task id #2

      TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
        Hist #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}

    Running activities (most recent first):

      TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=1}

        Run #1: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}

      TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}

        Run #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}

    mResumedActivity: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}


  Stack #0:

    Task id #1

      TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
        Hist #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}

    Running activities (most recent first):

      TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}

        Run #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}

  上面的栈信息是来自Android5.1.1。可以看到目前机器中有2个ActivityStack(Stack #0和Stack #1)。Stack #0中含有TaskRecord #1,TaskRecord #1含有一个代表Launcher的ActivityRecord。Stack #1中含有TaskRecord #3 和TaskRecord #2,TaskRecord #3含有一个代表com.a_task.application/.OtherActivity1的ActivityRecord,TaskRecord #2含有一个代表com.a_task.application/.MainActivity的ActivityRecord。
  从Display #0 (activities from top to bottom):这句话可以看出,ActivityRecord出现的顺序正是机器目前所有Activity的排列顺序。OtherActivity1位于顶部,Launcher位于底部。

  • 第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
    • 按下HOME键,打开app2
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)

Display #0 (activities from top to bottom):

  Stack #1:

    Task id #4

      TaskRecord{1f030017 #4 A=com.b_task.application2 U=0 sz=1}
        Hist #0: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}

    Task id #3

      TaskRecord{16b2f5ed #3 A=com.task.other.independent U=0 sz=1}
        Hist #0: ActivityRecord{1952693a u0 com.a_task.application/.OtherActivity1 t3}

    Task id #2

      TaskRecord{136f1c22 #2 A=com.a_task.application U=0 sz=1}
        Hist #0: ActivityRecord{210d00df u0 com.a_task.application/.MainActivity t2}
        
    Running activities (most recent first):

      TaskRecord{1f030017 #4 A=com.b_task.application2 U=0 sz=1}

        Run #2: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}

      TaskRecord{16b2f5ed #3 A=com.task.other.independent U=0 sz=1}

        Run #1: ActivityRecord{1952693a u0 com.a_task.application/.OtherActivity1 t3}

      TaskRecord{136f1c22 #2 A=com.a_task.application U=0 sz=1}

        Run #0: ActivityRecord{210d00df u0 com.a_task.application/.MainActivity t2}


    mResumedActivity: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}



  Stack #0:

    Task id #1

      TaskRecord{7183c04 #1 A=com.android.launcher3 U=0 sz=1}
        Hist #0: ActivityRecord{25eace7b u0 com.android.launcher3/.Launcher t1}

    Running activities (most recent first):

      TaskRecord{7183c04 #1 A=com.android.launcher3 U=0 sz=1}

        Run #0: ActivityRecord{25eace7b u0 com.android.launcher3/.Launcher t1}
  • 再打开app2的OtherActivity2页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)

Display #0 (activities from top to bottom):

  Stack #1:

    Task id #3

      TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}
        Hist #1: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}
        Hist #0: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}

    Task id #4

      TaskRecord{3d4399bb #4 A=com.b_task.application2 U=0 sz=1}
        Hist #0: ActivityRecord{3f04f4f7 u0 com.b_task.application2/.MainActivity t4}
        
    Task id #2

      TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
        Hist #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}

    Running activities (most recent first):

      TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}

        Run #3: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}

      TaskRecord{3d4399bb #4 A=com.b_task.application2 U=0 sz=1}

        Run #2: ActivityRecord{3f04f4f7 u0 com.b_task.application2/.MainActivity t4}

      TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}

        Run #1: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}

      TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}

        Run #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}

    mResumedActivity: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}


  Stack #0:

    Task id #1

      TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
        Hist #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}

    Running activities (most recent first):

      TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}

        Run #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}

  从上面的栈信息中我们可以看到当打开app2时,Task #4位于Task #3的上方。但是当我们打开app2的OtherActivity2页面时,Task #3就被移动到了Task #4的上方。这说明ActivityStack #1中的TaskRecord重排了顺序。而且app1和app2对应的ActivityStack都是Stack #1。
  我们再来看看在Android9的机器上重复上面的操作,栈信息是怎样的。

  • 第一阶段:先打开app1,再打开OtherActivity1页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):

  Stack #761: type=standard mode=fullscreen
    Task id #11652
    * TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
        Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

    Running activities (most recent first):
      TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
        Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

    mResumedActivity: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

  Stack #760: type=standard mode=fullscreen
    Task id #11651
    * TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
         
    Running activities (most recent first):
      TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}

  Stack #0: type=home mode=fullscreen
    Task id #1
    * TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}

    Running activities (most recent first):
      TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
  • 第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
    • 按下HOME键,打开app2
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):

  Stack #762: type=standard mode=fullscreen
    Task id #11653
    * TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
        Hist #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}

    Running activities (most recent first):
      TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
        Run #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}

    mResumedActivity: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}

  Stack #0: type=home mode=fullscreen
    Task id #1
    * TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
      
    Running activities (most recent first):
      TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}

  Stack #761: type=standard mode=fullscreen
    Task id #11652
    * TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
        Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

    Running activities (most recent first):
      TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
        Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

  Stack #760: type=standard mode=fullscreen
    Task id #11651
    * TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}

    Running activities (most recent first):
      TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
  • 再打开app2的OtherActivity2页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):

  Stack #761: type=standard mode=fullscreen
    Task id #11652
    * TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=2}
        Hist #1: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}
        Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
        
    Running activities (most recent first):
      TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=2}
        Run #1: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}
        Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}

    mResumedActivity: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}

  Stack #762: type=standard mode=fullscreen
    Task id #11653
    * TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
        Hist #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}

    Running activities (most recent first):
      TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
        Run #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}

  Stack #0: type=home mode=fullscreen
    Task id #1
    * TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}

    Running activities (most recent first):
      TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}

  Stack #760: type=standard mode=fullscreen
    Task id #11651
    * TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
        
    Running activities (most recent first):
      TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
        Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}

  从上面的栈信息可以看出来,在第一阶段时,app1有2个ActivityStack,分别是Stack #760和Stack #761,第二阶段时app2有属于自己的ActivityStack,即Stack #762,也有和app1共享的ActivityStack,即Stack #761。由此可见,在不同的Android版本下,APP与ActivityStack的对应关系不同。APP与ActivityStack之间并无必然的联系。有可能是一个APP对应一个ActivityStack,有可能是一个APP对应多个ActivityStack,也有可能是多个APP共用一个ActivityStack
在这里插入图片描述

ActivityStack的作用

  那么ActivityStack是用来做什么的?这个问题我在网上找了好久,也没有答案。以下说说我的理解。
  不知道大家有没有想过为什么要用这么多的ActivityStack来管理TaskRecord列表,而不是用一个ActivityStack管理全部的TaskRecord。下面假设只用一个ActivityStack管理全部的TaskRecord,那么在Android5.1.1的机器中执行了第二阶段后,栈信息会变成什么样?
在这里插入图片描述
  现在按下HOME键,我们来看下栈信息会怎么变。
在这里插入图片描述
  Android5.1.1的原栈中只需要将Stack #0移至列表头即可,需要3个步骤:

  1. 移除Stack #0并保存于临时变量中
  2. Stack #1移至列表底部
  3. 将Stack #0移至列表顶部

  此时的栈信息如下:

Stack #0:

    Task id #1

      TaskRecord{20b66655 #1 A=com.android.launcher3 U=0 sz=1}
        Hist #0: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}

    Running activities (most recent first):
      TaskRecord{20b66655 #1 A=com.android.launcher3 U=0 sz=1}
        Run #0: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}

    mResumedActivity: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}

Stack #1:

    Task id #3

      TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}
        Hist #1: ActivityRecord{22bb8f8a u0 com.b_task.application2/.OtherActivity2 t3}
        Hist #0: ActivityRecord{6fc682b u0 com.a_task.application/.OtherActivity1 t3}

    Task id #4

      TaskRecord{2405315b #4 A=com.b_task.application2 U=0 sz=1}
        Hist #0: ActivityRecord{92febef u0 com.b_task.application2/.MainActivity t4}

    Task id #2

      TaskRecord{32a1edf8 #2 A=com.a_task.application U=0 sz=1}
        Hist #0: ActivityRecord{3915bebe u0 com.a_task.application/.MainActivity t2}

    Running activities (most recent first):

      TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}

        Run #3: ActivityRecord{22bb8f8a u0 com.b_task.application2/.OtherActivity2 t3}

      TaskRecord{2405315b #4 A=com.b_task.application2 U=0 sz=1}

        Run #2: ActivityRecord{92febef u0 com.b_task.application2/.MainActivity t4}

      TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}

        Run #1: ActivityRecord{6fc682b u0 com.a_task.application/.OtherActivity1 t3}

      TaskRecord{32a1edf8 #2 A=com.a_task.application U=0 sz=1}

        Run #0: ActivityRecord{3915bebe u0 com.a_task.application/.MainActivity t2}

  如果只用一个ActivityStack管理所有的TaskRecord的话:
在这里插入图片描述
  我们可以看到需要5个步骤:

  1. 移除Task #1,并保存于临时变量
  2. Task #2向前移一位
  3. Task #4向前移一位
  4. Task #3向前移一位
  5. 将Task #1移至列表顶部

  显然效率低了很多。所以我得出一个结论:ActivityStack的作用是更快捷地将任务栈从后台调至前台
  由于app1的OtherActivity1的启动模式是singleTask,且单独为它指定了一个任务栈名。Android9.0就把OtherActivity1单独放在了一个ActivityStack中,之所以这么做,也是为了更快地调度任务栈。
在这里插入图片描述
  上图中,假设Task #2中含有启动模式为singleTask的Activity,现要启动该Activity,就需要把Task #2移至队列顶部(即前台)。

  Android5.1.1需要4个步骤:

  1. 移除Task #2,并保存于临时变量中
  2. Task #3向前移一位
  3. Task #4向前移一位
  4. 将Task #2移至Stack #1中的List<TaskRecord>的顶部

  Android9.0只需要3个步骤:

  1. 移除Stack #1,并保存于临时变量中
  2. Stack #2向前移一位
  3. 将Stack #1移至列表顶部

  显然Android9.0的效率更高。

ActivityDisplay

  ActivityDisplay表示一个屏幕,Android支持三种屏幕:主屏幕,外接屏幕(HDMI等),虚拟屏幕(投屏)。一般情况下,即只有主屏幕时,ActivityStackSupervisor与ActivityDisplay都是系统唯一;
  ActivityDisplay是ActivityStackSupervisor的内部类,它相当于一个工具类,封装了移除和添加ActivityStack的方法。

class ActivityDisplay {
	final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();

	void attachActivities(ActivityStack stack) {
            if (DEBUG_STACK) Slog.v(TAG_STACK,
                    "attachActivities: attaching " + stack + " to displayId=" + mDisplayId);
            mStacks.add(stack);
     }

	void detachActivitiesLocked(ActivityStack stack) {
            if (DEBUG_STACK) Slog.v(TAG_STACK, "detachActivitiesLocked: detaching " + stack
                    + " from displayId=" + mDisplayId);
            mStacks.remove(stack);
     }
}

ActivityStackSupervisor

  ActivityStackSupervisor是ActivityStack的管理者,内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个ActivityStack。其中,mHomeStack管理的是Launcher相关的Activity栈, stackId为0;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈。

public final class ActivityStackSupervisor implements DisplayListener {

	/** The stack containing the launcher app. Assumed to always be attached to
     * Display.DEFAULT_DISPLAY. */
    private ActivityStack mHomeStack;

    /** The stack currently receiving input or launching the next activity. */
    private ActivityStack mFocusedStack;

    /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
     * been resumed. If stacks are changing position this will hold the old stack until the new
     * stack becomes resumed after which it will be set to mFocusedStack. */
    private ActivityStack mLastFocusedStack;

	/** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
    private SparseArray<ActivityContainer> mActivityContainers = new SparseArray<>();

	ActivityStack createStackOnDisplay(int stackId, int displayId) {
        ……
        ActivityContainer activityContainer = new ActivityContainer(stackId);
        mActivityContainers.put(stackId, activityContainer);
        activityContainer.attachToDisplayLocked(activityDisplay);
        return activityContainer.mStack;
    }

	class ActivityContainer extends android.app.IActivityContainer.Stub {
			final ActivityStack mStack;
			ActivityDisplay mActivityDisplay;

			ActivityContainer(int stackId) {
            	synchronized (mService) {
                	mStackId = stackId;
                	mStack = new ActivityStack(this, mRecentTasks);
           		 }
        	}

			void attachToDisplayLocked(ActivityDisplay activityDisplay) {
            		……
					mActivityDisplay = activityDisplay;
            		activityDisplay.attachActivities(mStack);
       		 }

			protected void detachLocked() {
          		 ……
           		 if (mActivityDisplay != null) {
                	mActivityDisplay.detachActivitiesLocked(mStack);
           		 }
        	}
	}
}

  ActivityDisplay的添加和移除ActivityStack的方法又被封装进了ActivityContainer类中,ActivityStackSupervisor调用ActivityContainer的attachToDisplayLockeddetachLocked对ActivityStack列表进行重排序,将任务栈从后台切换至前台。

在这里插入图片描述

前台任务栈与后台任务栈

在这里插入图片描述
  如上图所示,只有Task #5才是前台任务栈,其余的都是后台任务栈。后台任务栈里面的Activity全部处于onStop状态。

参考文献:
Android-Activity所应该了解的大概就这样。(中)
四大组件之ActivityRecord

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值