ActivityRecord、TaskRecord、ActivityStack相互关系以及Activity启动模式
1.简介
先来张简单的关系图:
- 一个
ActivityRecord
对应一个Activity
,保存了一个Activity
的所有信息;但是一个Activity
可能会有多个ActivityRecord
,因为Activity
可以被多次启动,这个主要取决于其启动模式。 - 一个
TaskRecor
d由一个或者多个ActivityRecord
组成,这就是我们常说的任务栈,具有后进先出的特点。 ActivityStack
则是用来管理TaskRecord
的,包含了多个TaskRecord
。
下面进入详细的代码分析,本文源码基于android api27。
2.代码分析
2.1 ActivityRecord
ActivityRecord,源码中的注释介绍:An entry in the history stack, representing an activity。翻译:历史栈中的一个条目,代表一个activity。
frameworks/base/services/core/java/com/android/server/am/ActivityRecord.javafinal class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {final ActivityManagerService service; // ownerfinal IApplicationToken.Stub appToken; // window manager tokenAppWindowContainerController mWindowContainerController;final ActivityInfo info; // all about mefinal ApplicationInfo appInfo; // information about activity's app//省略其他成员变量//ActivityRecord所在的TaskRecordprivate 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
:
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.javaclass 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.2 TaskRecord
TaskRecord
,内部维护一个ArrayList<ActivityRecord>
用来保存ActivityRecord
。
frameworks/base/services/core/java/com/android/server/am/TaskRecord.javafinal class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {final int taskId; //任务IDfinal ArrayList<ActivityRecord> mActivities; //使用一个ArrayList来保存所有的ActivityRecordprivate 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
:
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.javaclass 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);//其他代码略}}}
2.3 ActivityStack
ActivityStack
,内部维护了一个ArrayList<TaskRecord>
,用来管理TaskRecord
。
frameworks/base/services/core/java/com/android/server/am/ActivityStack.javaclass ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener {private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();//使用一个ArrayList来保存TaskRecordfinal 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) {//创建一个taskTaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, voiceInteractor, type);//将task添加到ActivityStack中去addTask(task, toTop, "createTaskRecord");//其他代码略return task;}//添加Taskvoid 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到mTaskHistorytask.setStack(this);//为TaskRecord设置ActivityStack//...}//其他代码略}
- 可以看到
ActivityStack
使用了一个ArrayList
来保存TaskRecord
。 - 另外,
ActivityStack
中还持有ActivityStackSupervisor
对象,这个是用来管理ActivityStacks
的。
ActivityStack
是由ActivityStackSupervisor
来创建的,实际ActivityStackSupervisor
就是用来管理ActivityStack
的,继续看下面的ActivityStackSupervisor
分析。
2.4 ActivityStackSupervisor
ActivityStackSupervisor
,顾名思义,就是用来管理ActivityStack
的。
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javapublic class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {ActivityStack mHomeStack;//管理的是Launcher相关的任务ActivityStack mFocusedStack;//管理非Launcher相关的任务//创建ActivityStackActivityStack 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://创建一个ActivityStackreturn new ActivityStack(display, stackId, this, mRecentTasks, onTop);}}}
ActivityStackSupervisor
内部有两个不同的ActivityStack
对象:mHomeStack
、mFocusedStack
,用来管理不同的任务。ActivityStackSupervisor
内部包含了创建ActivityStack
对象的方法。
AMS初始化时会创建一个ActivityStackSupervisor
对象。
2.5 总结
所以,实际上,他们的关系应该是这样的:
3. 场景分析
下面通过启动Activity的代码来分析一下:
3.1 桌面
首先,我们看下处于桌面时的状态,运行命令:
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相关的任务。
3.2 从桌面启动一个Activity
从桌面启动一个APP,然后运行上面的命令,为了节省篇幅,这里和后面就不贴结果了,直接放图了。
从桌面点击图标启动一个AActivity
,可以看到,会多了一个Stack #1
,这个Stack #1
就是ActivityStackSupervisor
中的mFocusedStack
,mFocusedStack
负责管理的是非Launcher相关的任务。同时也会创建一个新的ActivityRecord
和TaskRecord
,ActivityRecord
放到TaskRecord
中,TaskRecord
则放进mFocusedStack
中。
3.3 默认模式从A启动B
然后,我们从AActivity
中启动一个BActivity
,可以看到会创建一个新的ActivityRecord
然后放到已有的TaskRecord
栈顶。
3.4 从A启动B创建新栈
如果我们想启动的BActivity
在一个新的栈中呢,我们可以用singleInstance
的方式来启动BActivity
。singleInstance
后面也会讲到。这种方式会创建一个新的ActivityRecord
和TaskRecord
,把ActivityRecord
放到新的TaskRecord
中去。
4. 流程分析
4.1 启动流程
这里对启动Activity过程中涉及到的ActivityStack
、TaskRecord
、ActivityRecord
、ActivityStackSupervisor
进行简单的分析,实际上一张时序图就可以看明白了。相关的代码可以看上面的内容。
简单总结:
startActivity
时首先会创建一个ActivityRecord
。- 如果有需要,会创建一个
TaskRecord
,并把这个TaskRecord
加入到ActivityStack
中。 - 将
ActivityRecord
添加到TaskRecord
的栈顶。
5. 启动模式
相信看完上面的介绍,现在再来看启动模式那是so easy了。
5.1 standerd
默认模式,每次启动Activity都会创建一个新的Activity实例。
比如:现在有个A Activity,我们在A上面启动B,再然后在B上面启动A,其过程如图所示:
5.2 singleTop
如果要启动的Activity已经在栈顶,则不会重新创建Activity,只会调用该该Activity的
onNewIntent()
方法。
如果要启动的Activity不在栈顶,则会重新创建该Activity的实例。
比如:现在有个A Activity,我们在A以standerd
模式上面启动B,然后在B上面以singleTop
模式启动A,其过程如图所示,这里会新创建一个A实例:
5.3 singleTask
如果要启动的Activity已经存在于它想要归属的栈中,那么不会创建该Activity实例,将栈中位于该Activity上的所有的Activity出栈,同时该Activity的
onNewIntent()
方法会被调用。
如果要启动的Activity不存在于它想要归属的栈中,并且该栈存在,则会创建该Activity的实例。
如果要启动的Activity想要归属的栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入到新栈中。
比如:现在有个A Activity,我们在A以standerd
模式上面启动B,然后在B上面以singleTask
模式启动A,其过程如图所示:
5.4 singleInstance
基本和
singleTask
一样,不同的是启动Activity时,首先要创建在一个新栈,然后创建该Activity实例并压入新栈中,新栈中只会存在这一个Activity实例。
比如:现在有个A Activity,我们在A以singleInstance
模式上面启动B,其过程如图所示:
6.Intent的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
默认具有此标记位的效果。
ActivityRecord、TaskRecord、ActivityStack相互关系以及Activity启动模式相关推荐
- activity 启动模式_Intent#FLAG_ACTIVITY_CLEAR_TOP 真的会 clear top 吗
一.背景 前段时间处理了一个 App 内草稿丢失的反馈,很多用户反馈连续存了多个草稿之后,草稿箱都只有一个草稿,显然是发生了草稿丢失.从用户反馈的数据来看,反馈用户的系统版本都在 Android 7. ...
- 深入理解Activity启动模式之大结局
谈起Activity的启动模式必不可少的要是launchMode.Flags.taskAffinity这三块知识点,上一篇文章 深入理解Activity启动模式之launchMode 看过的同学都知道 ...
- activity启动模式你所不知道的异常情况
前言 虽然了解activity的四种启动模式,但是在一些复杂场景下,各种启动模式会出现的现象,以及现象的原因并不清楚,再加上个taskAffinity launchMode clearTaskOnLa ...
- Android Activity 启动模式详解
最近有群里的朋友问我 Activity的四种启动模式分别是什么意思? 当初因为项目比较忙,草草的解释了下, Api文档中说的也只是一般,在这里就小记一下吧,以便有更多的朋友对Activity启动模式了 ...
- 深入理解Activity启动模式之launchMode
Android每个Application都是由若干个四大组件组成的.每个页面都是一个Activity,当需要打开相应页面(Activity)时系统会创建他们的实例并把他们一一放入栈中进行管理.任务栈是 ...
- activity 启动模式_腾讯大牛:你根本不懂Activity!
码个蛋(codeegg)第 583 次推文 作者:厘米姑娘 原文:https://www.jianshu.com/p/602b1ec4ca7a 在之前的Activity篇主要学习Activity的生命 ...
- Android中Activity启动模式
Android中Activity启动模式一共是四种,这里我写一下我对其的理解: 1.standard(默认) 2.singleTop,如果某个Activity设置了该属性,且当前Activity就是这 ...
- Android利用activity启动模式退出整个应用
Android利用activity启动模式退出整个应用 作者:翔星幻羽发布于:02月22日 13:39访问(22)评论(0) Android利用activity启动模式退出整个应用 分类: andro ...
- (二)Activity启动模式
启动模式 一.概念 顾名思义,就是activity的启动方式方法,共有4种模式standard,singleTop,singleTask,singleInstance. 为什么要学习启动模式呢?因为有 ...
最新文章
- 微电子科学与工程要学计算机吗,微电子科学与工程专业适合女生学习吗
- opencv线结构光三维重建
- 网站开发建设过程中所涉及到的技术问题应当如何面对?
- [云炬创业基础笔记]第二章创业者测试18
- kafka 削峰_从面试角度一文学完 Kafka
- oracle转成整型_Oracle中如何用SQL把字符串转换成整型
- em算法 实例 正态分布_Petuum提出序列生成学习算法通用框架
- 索尼推出 PlayStation 漏洞奖励计划,最严重漏洞5万美元起步
- eclipse如何设置自己喜欢的主题
- ucos操作系统(2)——OSTimeDly
- Android 阿里云镜像谷歌仓库
- YAPI自动生成接口文档,解放测试人生产力...
- c语言结构体memcmp,用memcmp()比较结构体
- c语言文件分割与合并
- html插入动态背景,HTML 动态背景
- 用力一瞥Android渲染机制-黄油计划
- 国内各银行间异地汇款手续费对照表
- Chrome浏览器自带翻译功能不能使用了?看我的解决方法
- Java学习第一周(2.20~2.24)
- 1.1 机器学习和深度学习综述