Android源碼進(jìn)階之ActivityRecord、TaskRecord、ActivityStack以及啟動(dòng)模式詳細(xì)分析
前言
activity啟動(dòng)時(shí)候會(huì)說(shuō)到activity棧,任務(wù)棧,activity任務(wù)棧等詞語(yǔ),但是如果細(xì)問(wèn)這些名詞的代表著什么?以什么表現(xiàn)形式出現(xiàn)?
一個(gè)ActivityRecord對(duì)應(yīng)一個(gè)Activity,保存了一個(gè)Activity的所有信息;但是一個(gè)Activity可能會(huì)有多個(gè)ActivityRecord,因?yàn)锳ctivity可以被多次啟動(dòng),這個(gè)主要取決于其啟動(dòng)模式;
一個(gè)TaskRecord由一個(gè)或者多個(gè)ActivityRecord組成,這就是我們常說(shuō)的任務(wù)棧,具有后進(jìn)先出的特點(diǎn);
ActivityStack則是用來(lái)管理TaskRecord的,包含了多個(gè)TaskRecord;
今天我們就來(lái)聊聊怎么管理activity以及任務(wù)棧等;
一、任務(wù)棧源碼解析
1、ActivityRecord
ActivityRecord:歷史棧中的一個(gè)條目,代表一個(gè)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.
- //構(gòu)造方法,需要傳遞大量信息
- 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) {
- }
- }
- 實(shí)際上,ActivityRecord中存在著大量的成員變量,包含了一個(gè)Activity的所有信息;
- ActivityRecord中的成員變量task表示其所在的TaskRecord,由此可以看出:ActivityRecord與TaskRecord建立了聯(lián)系;
startActivity()時(shí)會(huì)創(chuàng)建一個(gè)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,內(nèi)部維護(hù)一個(gè)ArrayList
- final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
- final int taskId; //任務(wù)ID
- final ArrayList<ActivityRecord> mActivities; //使用一個(gè)ArrayList來(lái)保存所有的ActivityRecord
- private ActivityStack mStack; //TaskRecord所在的ActivityStack
- //構(gòu)造方法
- 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設(shè)置TaskRecord,就是這里建立的聯(lián)系
- //...
- index = Math.min(size, index);
- mActivities.add(index, r);//添加到mActivities
- //...
- }
- //其他代碼略
- }
- 可以看到TaskRecord中使用了一個(gè)ArrayList來(lái)保存所有的ActivityRecord;
- 同樣,TaskRecord中的mStack表示其所在的ActivityStack;
startActivity()時(shí)也會(huì)創(chuàng)建一個(gè)TaskRecord;
- class ActivityStarter {
- private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
- mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
- if (mReuseTask == null) {
- //創(chuàng)建一個(gè)createTaskRecord,實(shí)際上是調(diào)用ActivityStack里面的createTaskRecord()方法,ActivityStack下面會(huì)講到
- 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,內(nèi)部維護(hù)了一個(gè)ArrayList
- class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener {
- private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();//使用一個(gè)ArrayList來(lái)保存TaskRecord
- final int mStackId;
- protected final ActivityStackSupervisor mStackSupervisor;//持有一個(gè)ActivityStackSupervisor,所有的運(yùn)行中的ActivityStacks都通過(guò)它來(lái)進(jìn)行管理
- //構(gòu)造方法
- 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)建一個(gè)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);//為T(mén)askRecord設(shè)置ActivityStack
- //...
- }
- //其他代碼略
- }
- 看到ActivityStack使用了一個(gè)ArrayList來(lái)保存TaskRecord;
- 另外,ActivityStack中還持有ActivityStackSupervisor對(duì)象,這個(gè)是用來(lái)管理ActivityStacks的;
- ActivityStack是由ActivityStackSupervisor來(lái)創(chuàng)建的,實(shí)際ActivityStackSupervisor就是用來(lái)管理ActivityStack的,繼續(xù)看下面的ActivityStackSupervisor分析;
4、ActivityStackSupervisor
ActivityStackSupervisor,顧名思義,就是用來(lái)管理ActivityStack的;
- ActivityStackSupervisor,顧名思義,就是用來(lái)管理ActivityStack的;
- public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
- ActivityStack mHomeStack;//管理的是Launcher相關(guān)的任務(wù)
- ActivityStack mFocusedStack;//管理非Launcher相關(guān)的任務(wù)
- //創(chuàng)建ActivityStack
- ActivityStack createStack(int stackId, ActivityStackSupervisor.ActivityDisplay display, boolean onTop) {
- switch (stackId) {
- case PINNED_STACK_ID:
- //PinnedActivityStack是ActivityStack的子類(lèi)
- return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop);
- default:
- //創(chuàng)建一個(gè)ActivityStack
- return new ActivityStack(display, stackId, this, mRecentTasks, onTop);
- }
- }
- }
- ActivityStackSupervisor內(nèi)部有兩個(gè)不同的ActivityStack對(duì)象:mHomeStack、mFocusedStack,用來(lái)管理不同的任務(wù);
- ActivityStackSupervisor內(nèi)部包含了創(chuàng)建ActivityStack對(duì)象的方法;
- AMS初始化時(shí)會(huì)創(chuàng)建一個(gè)ActivityStackSupervisor對(duì)象;
二、啟動(dòng)流程和啟動(dòng)模式看任務(wù)棧
1、啟動(dòng)流程
啟動(dòng)Activity過(guò)程中涉及到的ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor進(jìn)行簡(jiǎn)單的分析,實(shí)際上一張時(shí)序圖就可以看明白了
- startActivity時(shí)首先會(huì)創(chuàng)建一個(gè)ActivityRecord。
- 如果有需要,會(huì)創(chuàng)建一個(gè)TaskRecord,并把這個(gè)TaskRecord加入到ActivityStack中。
- 將ActivityRecord添加到TaskRecord的棧頂
2、啟動(dòng)模式中的任務(wù)棧
①standerd
默認(rèn)模式,每次啟動(dòng)Activity都會(huì)創(chuàng)建一個(gè)新的Activity實(shí)例
現(xiàn)在有個(gè)A Activity,我們?cè)贏上面啟動(dòng)B,再然后在B上面啟動(dòng)A,其過(guò)程如圖所示
②singleTop
- 如果要啟動(dòng)的Activity已經(jīng)在棧頂,則不會(huì)重新創(chuàng)建Activity,只會(huì)調(diào)用該該Activity的onNewIntent()方法。
- 如果要啟動(dòng)的Activity不在棧頂,則會(huì)重新創(chuàng)建該Activity的實(shí)例;
現(xiàn)在有個(gè)A Activity,我們?cè)贏以standerd模式上面啟動(dòng)B,然后在B上面以singleTop模式啟動(dòng)A,其過(guò)程如圖所示,這里會(huì)新創(chuàng)建一個(gè)A實(shí)例
B上面以singleTop模式啟動(dòng)B的話,則不會(huì)重新創(chuàng)建B,只會(huì)調(diào)用onNewIntent()方法,其過(guò)程如圖所示
③singleTask
- 如果要啟動(dòng)的Activity已經(jīng)存在于它想要?dú)w屬的棧中,那么不會(huì)創(chuàng)建該Activity實(shí)例,將棧中位于該Activity上的所有的Activity出棧,同時(shí)該Activity的onNewIntent()方法會(huì)被調(diào)用。
- 如果要啟動(dòng)的Activity不存在于它想要?dú)w屬的棧中,并且該棧存在,則會(huì)創(chuàng)建該Activity的實(shí)例。
- 如果要啟動(dòng)的Activity想要?dú)w屬的棧不存在,則首先要?jiǎng)?chuàng)建一個(gè)新棧,然后創(chuàng)建該Activity實(shí)例并壓入到新棧中
現(xiàn)在有個(gè)A Activity,我們?cè)贏以standerd模式上面啟動(dòng)B,然后在B上面以singleTask模式啟動(dòng)A,其過(guò)程如圖所示
④singleInstance
基本和singleTask一樣,不同的是啟動(dòng)Activity時(shí),首先要?jiǎng)?chuàng)建在一個(gè)新棧,然后創(chuàng)建該Activity實(shí)例并壓入新棧中,新棧中只會(huì)存在這一個(gè)Activity實(shí)例;
現(xiàn)在有個(gè)A Activity,我們?cè)贏以singleInstance模式上面啟動(dòng)B,其過(guò)程如圖所示:
3、啟動(dòng)Flag
startActivity()時(shí)往Intent 中加入相應(yīng)的標(biāo)志來(lái)指定啟動(dòng)模式,這種方式的優(yōu)先級(jí)會(huì)比在AndroidManifest中定義的優(yōu)先級(jí)高;但是AndroidManifest中只能定義四種啟動(dòng)方式:standard、singleTop、singleTask、singleInstance,而Intent的flag則有很多種。具體的可以看看文檔,我們這里看看部分flag:
- FLAG_ACTIVITY_NEW_TASK :跟launchMode中的singleTask一樣。
- FLAG_ACTIVITY_SINGLE_TOP :跟launchMode中的singleTop一樣。
- FLAG_ACTIVITY_CLEAR_TOP :launchMode中沒(méi)有對(duì)應(yīng)的值,如果要啟動(dòng)的Activity已經(jīng)存在于棧中,則將所有位于它上面的Activity出棧。singleTask默認(rèn)具有此標(biāo)記位的效果【責(zé)任編輯:武曉燕 TEL:(010)68476606】