前言
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()时会创建一个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()时也会创建一个TaskRecord;
- 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);
- //其他代码略
- }
- }
- }
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) {
- //创建一个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来创建的,实际ActivityStackSupervisor就是用来管理ActivityStack的,继续看下面的ActivityStackSupervisor分析;
4、ActivityStackSupervisor
ActivityStackSupervisor,顾名思义,就是用来管理ActivityStack的;
- ActivityStackSupervisor,顾名思义,就是用来管理ActivityStack的;
- 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);
- }
- }
- }
- ActivityStackSupervisor内部有两个不同的ActivityStack对象:mHomeStack、mFocusedStack,用来管理不同的任务;
- ActivityStackSupervisor内部包含了创建ActivityStack对象的方法;
- AMS初始化时会创建一个ActivityStackSupervisor对象;
二、启动流程和启动模式看任务栈
1、启动流程
启动Activity过程中涉及到的ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor进行简单的分析,实际上一张时序图就可以看明白了
- startActivity时首先会创建一个ActivityRecord。
- 如果有需要,会创建一个TaskRecord,并把这个TaskRecord加入到ActivityStack中。
- 将ActivityRecord添加到TaskRecord的栈顶
2、启动模式中的任务栈
①standerd
默认模式,每次启动Activity都会创建一个新的Activity实例
现在有个A Activity,我们在A上面启动B,再然后在B上面启动A,其过程如图所示
②singleTop
- 如果要启动的Activity已经在栈顶,则不会重新创建Activity,只会调用该该Activity的onNewIntent()方法。
- 如果要启动的Activity不在栈顶,则会重新创建该Activity的实例;
现在有个A Activity,我们在A以standerd模式上面启动B,然后在B上面以singleTop模式启动A,其过程如图所示,这里会新创建一个A实例
B上面以singleTop模式启动B的话,则不会重新创建B,只会调用onNewIntent()方法,其过程如图所示
③singleTask
- 如果要启动的Activity已经存在于它想要归属的栈中,那么不会创建该Activity实例,将栈中位于该Activity上的所有的Activity出栈,同时该Activity的onNewIntent()方法会被调用。
- 如果要启动的Activity不存在于它想要归属的栈中,并且该栈存在,则会创建该Activity的实例。
- 如果要启动的Activity想要归属的栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入到新栈中
现在有个A Activity,我们在A以standerd模式上面启动B,然后在B上面以singleTask模式启动A,其过程如图所示
④singleInstance
基本和singleTask一样,不同的是启动Activity时,首先要创建在一个新栈,然后创建该Activity实例并压入新栈中,新栈中只会存在这一个Activity实例;
现在有个A Activity,我们在A以singleInstance模式上面启动B,其过程如图所示:
3、启动Flag
startActivity()时往Intent 中加入相应的标志来指定启动模式,这种方式的优先级会比在AndroidManifest中定义的优先级高;但是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】