Android源碼進階之ActivityRecord、TaskRecord、ActivityStack以及啟動模式詳細分析
前言
activity啟動時候會說到activity棧,任務棧,activity任務棧等詞語,但是如果細問這些名詞的代表著什么?以什么表現形式出現?
一個ActivityRecord對應一個Activity,保存了一個Activity的所有信息;但是一個Activity可能會有多個ActivityRecord,因為Activity可以被多次啟動,這個主要取決于其啟動模式;
一個TaskRecord由一個或者多個ActivityRecord組成,這就是我們常說的任務棧,具有后進先出的特點;
ActivityStack則是用來管理TaskRecord的,包含了多個TaskRecord;
今天我們就來聊聊怎么管理activity以及任務棧等;
一、任務棧源碼解析
1、ActivityRecord
ActivityRecord:歷史棧中的一個條目,代表一個activity
- final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
- final ActivityManagerService service; // owner
- final IApplicationToken.Stub appToken; // window manager token
- AppWindowContainerController mWindowContainerController;
- final ActivityInfo info; // all about me
- final ApplicationInfo appInfo; // information about activity's app
- //省略其他成員變量
- //ActivityRecord所在的TaskRecord
- private TaskRecord task; // the task this is in.
- //構造方法,需要傳遞大量信息
- ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
- int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
- ActivityInfo aInfo, Configuration _configuration,
- com.android.server.am.ActivityRecord _resultTo, String _resultWho, int _reqCode,
- boolean _componentSpecified, boolean _rootVoiceInteraction,
- ActivityStackSupervisor supervisor, ActivityOptions options,
- com.android.server.am.ActivityRecord sourceRecord) {
- }
- }
- 實際上,ActivityRecord中存在著大量的成員變量,包含了一個Activity的所有信息;
- ActivityRecord中的成員變量task表示其所在的TaskRecord,由此可以看出:ActivityRecord與TaskRecord建立了聯系;
startActivity()時會創(chuàng)建一個ActivityRecord
- class ActivityStarter {
- private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
- String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
- String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
- ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
- com.android.server.am.ActivityRecord[] outActivity, TaskRecord inTask) {
- //其他代碼略
- ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
- callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
- resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
- mSupervisor, options, sourceRecord);
- //其他代碼略
- }
- }
2、TaskRecord
TaskRecord,內部維護一個ArrayList
- final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
- final int taskId; //任務ID
- final ArrayList<ActivityRecord> mActivities; //使用一個ArrayList來保存所有的ActivityRecord
- private ActivityStack mStack; //TaskRecord所在的ActivityStack
- //構造方法
- TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
- IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
- }
- //添加Activity到頂部
- void addActivityToTop(com.android.server.am.ActivityRecord r) {
- addActivityAtIndex(mActivities.size(), r);
- }
- //添加Activity到指定的索引位置
- void addActivityAtIndex(int index, ActivityRecord r) {
- //...
- r.setTask(this);//為ActivityRecord設置TaskRecord,就是這里建立的聯系
- //...
- index = Math.min(size, index);
- mActivities.add(index, r);//添加到mActivities
- //...
- }
- //其他代碼略
- }
- 可以看到TaskRecord中使用了一個ArrayList來保存所有的ActivityRecord;
- 同樣,TaskRecord中的mStack表示其所在的ActivityStack;
startActivity()時也會創(chuàng)建一個TaskRecord;
- class ActivityStarter {
- private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
- mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
- if (mReuseTask == null) {
- //創(chuàng)建一個createTaskRecord,實際上是調用ActivityStack里面的createTaskRecord()方法,ActivityStack下面會講到
- final TaskRecord task = mTargetStack.createTaskRecord(
- mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
- mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
- mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
- mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
- //其他代碼略
- }
- }
- }
3、ActivityStack
ActivityStack,內部維護了一個ArrayList
- class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener {
- private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();//使用一個ArrayList來保存TaskRecord
- final int mStackId;
- protected final ActivityStackSupervisor mStackSupervisor;//持有一個ActivityStackSupervisor,所有的運行中的ActivityStacks都通過它來進行管理
- //構造方法
- ActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId,
- ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) {
- }
- TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop, int type) {
- //創(chuàng)建一個task
- TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, voiceInteractor, type);
- //將task添加到ActivityStack中去
- addTask(task, toTop, "createTaskRecord");
- //其他代碼略
- return task;
- }
- //添加Task
- void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
- //其他代碼略
- }
- //添加Task到指定位置
- void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
- String reason) {
- mTaskHistory.remove(task);//若存在,先移除
- //...
- mTaskHistory.add(position, task);//添加task到mTaskHistory
- task.setStack(this);//為TaskRecord設置ActivityStack
- //...
- }
- //其他代碼略
- }
- 看到ActivityStack使用了一個ArrayList來保存TaskRecord;
- 另外,ActivityStack中還持有ActivityStackSupervisor對象,這個是用來管理ActivityStacks的;
- ActivityStack是由ActivityStackSupervisor來創(chuàng)建的,實際ActivityStackSupervisor就是用來管理ActivityStack的,繼續(xù)看下面的ActivityStackSupervisor分析;
4、ActivityStackSupervisor
ActivityStackSupervisor,顧名思義,就是用來管理ActivityStack的;
- ActivityStackSupervisor,顧名思義,就是用來管理ActivityStack的;
- public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
- ActivityStack mHomeStack;//管理的是Launcher相關的任務
- ActivityStack mFocusedStack;//管理非Launcher相關的任務
- //創(chuàng)建ActivityStack
- ActivityStack createStack(int stackId, ActivityStackSupervisor.ActivityDisplay display, boolean onTop) {
- switch (stackId) {
- case PINNED_STACK_ID:
- //PinnedActivityStack是ActivityStack的子類
- return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop);
- default:
- //創(chuàng)建一個ActivityStack
- return new ActivityStack(display, stackId, this, mRecentTasks, onTop);
- }
- }
- }
- ActivityStackSupervisor內部有兩個不同的ActivityStack對象:mHomeStack、mFocusedStack,用來管理不同的任務;
- ActivityStackSupervisor內部包含了創(chuàng)建ActivityStack對象的方法;
- AMS初始化時會創(chuàng)建一個ActivityStackSupervisor對象;
二、啟動流程和啟動模式看任務棧
1、啟動流程
啟動Activity過程中涉及到的ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor進行簡單的分析,實際上一張時序圖就可以看明白了
- startActivity時首先會創(chuàng)建一個ActivityRecord。
- 如果有需要,會創(chuàng)建一個TaskRecord,并把這個TaskRecord加入到ActivityStack中。
- 將ActivityRecord添加到TaskRecord的棧頂
2、啟動模式中的任務棧
①standerd
默認模式,每次啟動Activity都會創(chuàng)建一個新的Activity實例
現在有個A Activity,我們在A上面啟動B,再然后在B上面啟動A,其過程如圖所示
②singleTop
- 如果要啟動的Activity已經在棧頂,則不會重新創(chuàng)建Activity,只會調用該該Activity的onNewIntent()方法。
- 如果要啟動的Activity不在棧頂,則會重新創(chuàng)建該Activity的實例;
現在有個A Activity,我們在A以standerd模式上面啟動B,然后在B上面以singleTop模式啟動A,其過程如圖所示,這里會新創(chuàng)建一個A實例
B上面以singleTop模式啟動B的話,則不會重新創(chuàng)建B,只會調用onNewIntent()方法,其過程如圖所示
③singleTask
- 如果要啟動的Activity已經存在于它想要歸屬的棧中,那么不會創(chuàng)建該Activity實例,將棧中位于該Activity上的所有的Activity出棧,同時該Activity的onNewIntent()方法會被調用。
- 如果要啟動的Activity不存在于它想要歸屬的棧中,并且該棧存在,則會創(chuàng)建該Activity的實例。
- 如果要啟動的Activity想要歸屬的棧不存在,則首先要創(chuàng)建一個新棧,然后創(chuàng)建該Activity實例并壓入到新棧中
現在有個A Activity,我們在A以standerd模式上面啟動B,然后在B上面以singleTask模式啟動A,其過程如圖所示
④singleInstance
基本和singleTask一樣,不同的是啟動Activity時,首先要創(chuàng)建在一個新棧,然后創(chuàng)建該Activity實例并壓入新棧中,新棧中只會存在這一個Activity實例;
現在有個A Activity,我們在A以singleInstance模式上面啟動B,其過程如圖所示:
3、啟動Flag
startActivity()時往Intent 中加入相應的標志來指定啟動模式,這種方式的優(yōu)先級會比在AndroidManifest中定義的優(yōu)先級高;但是AndroidManifest中只能定義四種啟動方式:standard、singleTop、singleTask、singleInstance,而Intent的flag則有很多種。具體的可以看看文檔,我們這里看看部分flag:
- FLAG_ACTIVITY_NEW_TASK :跟launchMode中的singleTask一樣。
- FLAG_ACTIVITY_SINGLE_TOP :跟launchMode中的singleTop一樣。
- FLAG_ACTIVITY_CLEAR_TOP :launchMode中沒有對應的值,如果要啟動的Activity已經存在于棧中,則將所有位于它上面的Activity出棧。singleTask默認具有此標記位的效果【責任編輯:武曉燕 TEL:(010)68476606】