最近看4,4的源码,跟网上讲的ams变的太多了,那个什么mMainStack,还有什么mHistoryRecord等根本找不到,看的一头雾水,先总结下基本的数据结构吧。
其实说白了,他所谓的stack全部都是ArrayList,用ArrayList来模拟stack,开始还很纳闷既然是stack怎么去里边找activity,不是操作栈顶元素么?
全局一个总的stack:
/** All the non-launcher stacks */
private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
这个mStacks存储了所有的stack,其中每一个stack中存储是一个个的task,每一个task中存储的是一堆activity。
总体的大小关系是:
mStacks>Stack>task【开始没搞清楚大小关系,纠结了半天,从这个代码就可以看出】
void removeTask(TaskRecord task) {
mWindowManager.removeTask(task.taskId);
final ActivityStack stack = task.stack;
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.task == task) {
stack.mResumedActivity = null;
}
if (stack.removeTask(task) && !stack.isHomeStack()) {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
mStacks.remove(stack);
final int stackId = stack.mStackId;
final int nextStackId = mWindowManager.removeStack(stackId);
// TODO: Perhaps we need to let the ActivityManager determine the next focus...
if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
// If this is the last app stack, set mFocusedStack to null.
mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
}
}
}
这里删除是个task,首先拿到这个task所在的stack,就是第3行代码,然后删除掉这个stack中的task,然后注意这行代码:
mStacks.remove(stack);
为毛我只删除个task,你就要把我的stack也删掉?难不成task>stack??
关键点在这:
if (stack.removeTask(task) && !stack.isHomeStack()) {
这个if语句,我们回到stack中去看看他的removeTask的实现:
boolean removeTask(TaskRecord task) {
final int taskNdx = mTaskHistory.indexOf(task);
final int topTaskNdx = mTaskHistory.size() - 1;
if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
}
mTaskHistory.remove(task);
return mTaskHistory.isEmpty();
}
原来在stack中删除task的时候,最后会做出个判断,看当前stack中的task是否为空,如果为没东西了,那么这个stack也就可以删除了。
这也就证明了mStacks>stack>task
遍观整个ActivityStackSupervisor.java会发现其实关于stack除了mStacks是整个stack的集合,一共也就2个stack,分别是:
/** The stack containing the launcher app */
private ActivityStack mHomeStack;
/** The non-home stack currently receiving input or launching the next activity. If home is
* in front then mHomeStack overrides mFocusedStack.
* DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
private ActivityStack mFocusedStack;
就这2个东西,
mHomeStack存储luncher相关的内容,也就是home,另一个存储当前处于焦点的stack,mHomeStack会在开机之后自动加入到mStacks中去,而且只占据第0号位置,mFocusedStack占据第1号位置,
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);//初始化home
mStacks.add(mHomeStack);
}
调试的时候开启了10多个应用,发现这些应用的activity全部放到了mFocusedStack中,mStacks中第2个位置始终没有被使用,很纳闷,不知道是不是我应用开的不够多,如果仅仅用2个位置的话,那么要mStacks岂不是多此一举?这个还得好好琢磨琢磨。
看这个:
ActivityStack getLastStack() {
switch (mStackState) {
case STACK_STATE_HOME_IN_FRONT:
case STACK_STATE_HOME_TO_BACK:
return mHomeStack;
case STACK_STATE_HOME_TO_FRONT:
case STACK_STATE_HOME_IN_BACK:
default:
return mFocusedStack;
}
}
貌似就是在这两个stack中来回切换,关于是否会使用第3个位置,还有需要进一步确认。