先來張簡單的關係圖:java
ActivityStack、TaskRecord、ActivityRecord關係圖android
下面進入詳細的代碼分析,本文源碼基於android 27。shell
ActivityRecord,源碼中的註釋介紹:An entry in the history stack, representing an activity. 翻譯:歷史棧中的一個條目,表明一個activity。app
frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
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) {
}
}
複製代碼
startActivity()時會建立一個ActivityRecord:this
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
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);
//其餘代碼略
}
}
複製代碼
TaskRecord,內部維護一個ArrayList用來保存ActivityRecord。google
frameworks/base/services/core/java/com/android/server/am/TaskRecord.java
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
//...
}
//其餘代碼略
}
複製代碼
startActivity()時也會建立一個TaskRecord:spa
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
class ActivityStarter {
private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
if (mReuseTask == null) {
//建立一個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);
//其餘代碼略
}
}
}
複製代碼
ActivityStack,內部維護了一個ArrayList,用來管理TaskRecord。翻譯
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
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) {
//建立一個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是由ActivityStackSupervisor來建立的,實際ActivityStackSupervisor就是用來管理ActivityStack的,繼續看下面的ActivityStackSupervisor分析。3d
ActivityStackSupervisor,顧名思義,就是用來管理ActivityStack的。code
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
ActivityStack mHomeStack;//管理的是Launcher相關的任務
ActivityStack mFocusedStack;//管理非Launcher相關的任務
//建立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:
//建立一個ActivityStack
return new ActivityStack(display, stackId, this, mRecentTasks, onTop);
}
}
}
複製代碼
AMS初始化時會建立一個ActivityStackSupervisor對象。
因此,實際上,他們的關係應該是這樣的:
ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor關係圖
下面經過啓動Activity的代碼來分析一下:
首先,咱們看下處於桌面時的狀態,運行命令:
adb shell dumpsys activity
複製代碼
結果以下:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #0:
//中間省略其餘...
Task id #102
//中間省略其餘...
TaskRecord{446ae9e #102 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity }
Hist #0: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity }
ProcessRecord{19c7c43 2203:com.google.android.apps.nexuslauncher/u0a22}
Running activities (most recent first):
TaskRecord{446ae9e #102 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
Run #0: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}
mResumedActivity: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}
//省略其餘
複製代碼
實際上就是以下圖所示的結構,這裏的Stack #0就是ActivityStackSupervisor中的mHomeStack,mHomeStack管理的是Launcher相關的任務。
桌面下的狀態
從桌面啓動一個APP,而後運行上面的命令,爲了節省篇幅,這裏和後面就不貼結果了,直接放圖了。
從桌面點擊圖標啓動一個AActivity,能夠看到,會多了一個Stack #1,這個Stack #1就是ActivityStackSupervisor中的mFocusedStack,mFocusedStack負責管理的是非Launcher相關的任務。同時也會建立一個新的ActivityRecord和TaskRecord,ActivityRecord放到TaskRecord中,TaskRecord則放進mFocusedStack中。
啓動A
而後,咱們從AActivity中啓動一個BActivity,能夠看到會建立一個新的ActivityRecord而後放到已有的TaskRecord棧頂。
默認(standerd)模式啓動B
若是咱們想啓動的BActivity在一個新的棧中呢,咱們能夠用singleInstance的方式來啓動BActivity。singleInstance後面也會講到。這種方式會建立一個新的ActivityRecord和TaskRecord,把ActivityRecord放到新的TaskRecord中去。
啓動新Task
這裏對啓動Activity過程當中涉及到的ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor進行簡單的分析,實際上一張時序圖就能夠看明白了。相關的代碼能夠看上面的內容。
Activity啓動UML類圖
簡單總結: 1.startActivity時首先會建立一個ActivityRecord。 2.若是有須要,會建立一個TaskRecord,並把這個TaskRecord加入到ActivityStack中。 3.將ActivityRecord添加到TaskRecord的棧頂。
相信看完上面的介紹,如今再來看啓動模式那是so easy了。
默認模式,每次啓動Activity都會建立一個新的Activity實例。
好比:如今有個A Activity,咱們在A上面啓動B,再而後在B上面啓動A,其過程如圖所示:
standerd若是要啓動的Activity已經在棧頂,則不會從新建立Activity,只會調用該該Activity的onNewIntent()方法。 若是要啓動的Activity不在棧頂,則會從新建立該Activity的實例。
好比:如今有個A Activity,咱們在A以standerd模式上面啓動B,而後在B上面以singleTop模式啓動A,其過程如圖所示,這裏會新建立一個A實例:
singleTop_A
若是在B上面以singleTop模式啓動B的話,則不會從新建立B,只會調用onNewIntent()方法,其過程如圖所示:
singleTop_B.png
若是要啓動的Activity已經存在於它想要歸屬的棧中,那麼不會建立該Activity實例,將棧中位於該Activity上的全部的Activity出棧,同時該Activity的onNewIntent()方法會被調用。 若是要啓動的Activity不存在於它想要歸屬的棧中,而且該棧存在,則會建立該Activity的實例。 若是要啓動的Activity想要歸屬的棧不存在,則首先要建立一個新棧,而後建立該Activity實例並壓入到新棧中。
好比:如今有個A Activity,咱們在A以standerd模式上面啓動B,而後在B上面以singleTask模式啓動A,其過程如圖所示:
singleTask
基本和singleTask同樣,不一樣的是啓動Activity時,首先要建立在一個新棧,而後建立該Activity實例並壓入新棧中,新棧中只會存在這一個Activity實例。
好比:如今有個A Activity,咱們在A以singleInstance模式上面啓動B,其過程如圖所示:
singleInstance
另外,若是startActivity()時往Intent 中加入相應的標誌來指定啓動模式,這種方式的優先級會比在AndroidManifest中定義的優先級高;可是AndroidManifest中只能定義四種啓動方式:standard、singleTop、singleTask、singleInstance,而Intent的flag則有不少種。具體的能夠看看文檔,咱們這裏看看部分flag: