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实例。它用来存储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是栈的意思,那ActivityStack就表示“Activity的栈”?其实不是。从下面的代码中可以看出ActivityStack维护的是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<>();
}

  也有人说是一个应用一个ActivityStack。其实也不是。接下来就用命令行——adb shell dumpsys activity,来验证下。
  先准备2个APP。app1和app2各自都有两个页面,各自的启动页都是普通常见的,然后各自的都有另外一个其他页面,这分属于两个app的其他页面我们都给他们指定同一个任务栈名(这个任务栈名不跟任意一个app包名相同)。
  也就是说app1里面有MainActivity和OtherActivity1。app2里面有MainActivity和OtherActivity2。两个应用的MainActivity都是普通的Standard启动模式,而OtherActivity1和OtherActivity2都在清单文件指定了同一个自定义的任务栈名称和singelTask启动模式。
  我们这样操作:
  第一阶段:先打开app1,再打开OtherActivity1页面,接着按下home键。
  第二阶段:(接按下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页面,接着按下home键。
    在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 #18

      TaskRecord{35556de #18 A=com.task.other.independent U=0 sz=1}

        Hist #0: ActivityRecord{1aac911c u0 com.a_task.application/.OtherActivity1 t18}

    Task id #17

      TaskRecord{3981d0bf #17 A=com.a_task.application U=0 sz=1}

        Hist #0: ActivityRecord{31a500b5 u0 com.a_task.application/.MainActivity t17}


    Running activities (most recent first):

      TaskRecord{35556de #18 A=com.task.other.independent U=0 sz=1}

        Run #1: ActivityRecord{1aac911c u0 com.a_task.application/.OtherActivity1 t18}

      TaskRecord{3981d0bf #17 A=com.a_task.application U=0 sz=1}

        Run #0: ActivityRecord{31a500b5 u0 com.a_task.application/.MainActivity t17}



    mResumedActivity: ActivityRecord{1aac911c u0 com.a_task.application/.OtherActivity1 t18}



  Stack #0:

    Task id #1

      TaskRecord{3c9a438c #1 A=com.android.launcher3 U=0 sz=1}

        Hist #0: ActivityRecord{91e63b0 u0 com.android.launcher3/.Launcher t1}


    Running activities (most recent first):

      TaskRecord{3c9a438c #1 A=com.android.launcher3 U=0 sz=1}

        Run #0: ActivityRecord{91e63b0 u0 com.android.launcher3/.Launcher t1}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章