最近在閱讀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}