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}



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