Activity存储结构变化:从Android2.3到Android4.4
来源:互联网 发布:电脑网络接口类型 编辑:程序博客网 时间:2024/05/21 00:16
由于Android2.3操作系统的普及性,现有的对于Activity存储结构的分析大多是针对Android2.3的,但是,在目前最新的Android4.4中,Activity的存储结构发生了一些变化。下面就对这一变化做一描述。
基础知识:activity在AMS中的形式是ActivityRecord,task在AMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord。
一、Android2.3中Activity的存储结构
存储结构示意图:
AMS提供了一个ArrayList mHistory来管理所有的activity。
由上面的示意图可以得知:
(1)所有的ActivityRecord会被存储在mHistory管理;.
(2) 每个ActivityRecord会对应到一个TaskRecord,并且有着相同TaskRecord的ActivityRecord在mHistory中会处在连续的位置;
(3)同一个TaskRecord的Activity可能分别处于不同的进程中,每个Activity所处的进程跟task没有关系。
二、Android4.4中Activity的存储结构
在Android4.4中,并不采用原先的mHistory来管理所有的Activity,而是按层次进行管理。
由上图可以得知;
(1)在管理层次的最上层是一个ActivityStack类型的数组mStacks,用于管理所有的ActivityStack。
(2)当前,系统中只有两个ActivityStack,一个是mHomeStack,用于保存Launcher的Activity,另一个是mFocusedStack,用于保存非Launcher的App的Activity。
(3)mStacks数组中,只有上述的两个栈,设置数组的目的可能是为以后版本的多用户情况考虑,可能每个用户分别拥有自己的一个Activity,运行自己的App,当然这只是猜测。
(4)在每个ActivityStack中,都可以拥有多个TaskRecord。这些TaskRecord存储在ActivityStack.java:ArrayList<TaskRecord> mTaskHistory之中。
(5)在TaskRecord中,包含ArrayList<ActivityRecord> mActivities,用于存放该Task中的所有的Activity的信息;包含ActivityStack stack,用于记录所属的栈;包含int numActivities,用于记录当前Task中的Activity数量。
(6)Stack和Task中的存储:通过加断点对系统进行调试得知,mTaskHistory默认是一个容量为12的数组,当开的Task多于12个时,再开辟6个TaskRecord的用于存放新的Task信息。多于18个Task的情况没有进行测试。mStacks和mTaskHistory的存储情况相同。
(7)综合上面的分析可知,要想找到某个Activity,需要按层次查找:先找到对应的栈,再找到栈中的Task,再在该Task中查找Activity。
需要注意的是:
(1)不论Launcher(即Home)在前台还是后台,mFocusedStack的Id始终都是非Launcher所在的Stack的Id。
三、向已有的Task中添加一个Activity
既然Android2.3和Android4.4中对Activity的存储方式存在差异,那么添加一个新的Activity的时候,添加方法也是有差异的。
分析Activity的启动过程(具体可以查看老罗的《Android源代码情景分析》一书),在ActivityStack.startActivityUncheckedLocked函数中会判断决定是否需要为新开启的Activity创建新的Task,如果需要创建,那么就创建新的Task,如果不需要创建,那么就将Activity添加到原先已经存在的Task中。在此,我们只考虑后一种情况。进行完上述操作之后,执行ActivityStack.startActivityLocked()将Activity添加到Task中(ASS中也有startActivityLocked(),注意不要混淆)。
在Android2.3中:
public class ActivityStack {......private final void startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume) {final int NH = mHistory.size();int addPos = -1;if (!newTask) {// If starting in an existing task, find where that is...boolean startIt = true;for (int i = NH-1; i >= 0; i--) {ActivityRecord p = (ActivityRecord)mHistory.get(i);if (p.finishing) {continue;}if (p.task == r.task) {// Here it is! Now, if this is not yet visible to the// user, then just add it without starting; it will// get started when the user navigates back to it.addPos = i+1;if (!startIt) {mHistory.add(addPos, r);r.inHistory = true;r.task.numActivities++;mService.mWindowManager.addAppToken(addPos, r, r.task.taskId,r.info.screenOrientation, r.fullscreen);if (VALIDATE_TOKENS) {mService.mWindowManager.validateAppTokens(mHistory);}return;}break;}if (p.fullscreen) {startIt = false;}}}......// Slot the activity into the history stack and proceedmHistory.add(addPos, r);r.inHistory = true;r.frontOfTask = newTask;r.task.numActivities++;......if (doResume) {resumeTopActivityLocked(null);}}......}
由上述代码可知:
在Android2.3中,由于以下三个原因:(1)Activity是统一由mHistory数组来管理的(2)属于同一个Task的所有Activity都连续存放(3)新开启的Activity存放位置在以前开启的Activity之上,所以,当要添加新的Activity的时候,直接从上到下遍历mHistory数组,当检查到某个ActivityRecord所属的Task与新添加的Activity所属的Task相同时,记录该Activity在mHistory中的存放位置i,addPos=i+1即为要添加的Activity在mHistory中的位置,调用mHistory.add(addPos,r)就将Activity添加到mHistory数组中了。与此同时,满足了上述的三点要求。
在Android4.4中:
TaskRecord task = null;
if (!newTask) {
// If starting in an existing task, find where that is... boolean startIt = true; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { task = mTaskHistory.get(taskNdx); if (task == r.task) { // Here it is! Now, if this is not yet visible to the // user, then just add it without starting; it will // get started when the user navigates back to it. if (!startIt) { if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " + task, new RuntimeException("here").fillInStackTrace()); task.addActivityToTop(r); r.putInHistory(); mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } ActivityOptions.abort(options); return; } break; } else if (task.numFullscreen > 0) { startIt = false; } } }
由上述代码可以看出:
在Android4.4中,首先会从上到下遍历mTaskHistory数组,找到要启动的Activity所属的Task,之后直接调用Task.addActivityToTop(r)将Activity加入到该Task即可。接着调用r.puInHistory()进行善后事宜:
void putInHistory() { if (!inHistory) { inHistory = true; if (task != null && !finishing) { task.numActivities++; } } }
在该函数中,将inHistory标志位设置为TRUE,将所述的Task的numActivities参数加一。
- Activity存储结构变化:从Android2.3到Android4.4
- 从一个Activity到另一个Activity生命周期变化
- android4.4 evaluateJavascript 到android2.X上不能调用的问题
- android4.0 android2.3等下载地址 嘻嘻 希望能帮助到你们!!!!!!
- Android2.2、Android2.3 、Android4.0 audio hardware模块分析
- Android2.3 短信接收 从 framework 到 MMS.apk 小记
- Android4.0 与 android2.3 差异
- Android4.0 与 android2.3 差异
- Android4.0与Android2.3源代码差异
- Android4.0 与 android2.3 差异
- Android4.2到5.0 Phone的变化
- Android2.3 Home-Key、Activity
- Android4.4Phone的变化
- 从android1.1到android2.2
- Android4.4之Camera2预览流程(从APP到Driver)
- Android4.0,Android2.0
- 从NSM到Parquet:存储结构的衍化
- 从NSM到Parquet:存储结构的衍化
- EXTJS 之 Ext.PagingToolbar 的使用方法
- c语言 随机数
- mysql 数据库下视图使用
- 2014年阿里巴巴9月14号笔试题
- POJ 2886 Who Gets the Most Candies?
- Activity存储结构变化:从Android2.3到Android4.4
- rm: cannot remove `/home/cn0000/log/formlog.20140417': Read-only file system
- 使用gradle打包jar包
- IP address Check
- 中国最火开博啦~~~
- W5100常见问题汇总
- 矩陣入門 poj 3735
- 在DWR中调用Http Servlet 对象
- 【字符 BF 和 KMP算法】