首页 > 代码库 > DisplayContent、StackBox、TaskStack笔记
DisplayContent、StackBox、TaskStack笔记
文章仅记录自己的一点理解,仅供自己参考。
每个显示设备,都有一个Display对象,DisplayManagerService专门管理这些Display。
1、DisplayContent()
<span style="font-size:18px;"> DisplayContent(Display display, WindowManagerService service) { mDisplay = display; mDisplayId = display.getDisplayId(); display.getDisplayInfo(mDisplayInfo); isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; mService = service; StackBox newBox = new StackBox(service, this, null); mStackBoxes.add(newBox); TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this); newStack.mStackBox = newBox; newBox.mStack = newStack; mHomeStack = newStack; }</span>
对应在WMS中,每个Display对象都会给他new一个DisplayContent,保存跟这个Display相关的窗口等信息,这点从WMS的构造函数可以看出来。从DisplayContent()构造函数中还可以看出,每一个DisplayContent至少包含一个StackBox和TaskStack
createDisplayContentLocked()-->getDisplayContentLocked()-->WMS.newDisplayContentLocked()-->new DisplayContent();
<span style="font-size:18px;">WindowManagerService(){ ............ Display[] displays = mDisplayManager.getDisplays(); for (Display display : displays) { createDisplayContentLocked(display); } ........ }</span>
2、mInitialDisplayWidth、mInitialDisplayHeight、mInitialDisplayDensity
保存的是初始屏幕宽度、高度、密度
3、mDisplayInfo
由第1条中的DisplayContent()构造函数中可以看出,mDisplayInfo就是从Display中获取的,保存着Display的相关信息。
4、layoutNeeded
当有窗口需要Layout时,layoutNeeded就会被设为true。
5、mStackBoxes
正常来说mStackBoxes中会保存两个StackBox,一个StackBox(0)里面只包含Launcher,另一个StackBox包含所有其他窗口。
①StackBox.mParent
<span style="font-size:18px;"> /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this * is this entire size of mDisplayContent. */</span>mParent表示由哪个StackBox分裂而来,但是对于StackBox 0和StackBox 1的mParent都为null。
②StackBox.mBounds
WMS.performLayoutLockedInner()-->DisplayContent.setStackBoxSize()-->StackBox.setStackBoxSizes()-->mBounds.set(bounds);
bounds尺寸来源于mPolicy.getContentRectLw(bounds);
<span style="font-size:18px;"> public void getContentRectLw(Rect r) { r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); }</span>对于720*1280尺寸的手机,(mContentLeft, mContentTop, mContentRight, mContentBottom)=(0,50,720,1280),踢出了状态栏高度,因此mBounds=(0,50,720,1280)
③StackBox.mVertical
这个变量表示mFirst 和mSecond分裂方向是否是垂直分裂还是左右分裂,具体见split()函数。
/** Relative orientation of mFirst and mSecond. */
④StackBox.layoutNeeded
⑤StackBox.
⑥StackBox.mStack
/** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */
6、StackBox.split()
StackBox分裂函数,分裂的两个StackBox分别保存在mFirst和mSecond中(二叉树方式分裂)。
<span style="font-size:18px;"> TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) { if (mStackBoxId != relativeStackBoxId) { if (mStack != null) { return null; } TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight); if (stack != null) { return stack; } return mSecond.split(stackId, relativeStackBoxId, position, weight); } TaskStack stack = new TaskStack(mService, stackId, mDisplayContent); TaskStack firstStack; TaskStack secondStack; if (position == TASK_STACK_GOES_BEFORE) { position = TASK_STACK_TO_LEFT_OF; } else if (position == TASK_STACK_GOES_AFTER) { // TODO: Test Configuration here for LTR/RTL. position = TASK_STACK_TO_RIGHT_OF; } switch (position) { default: case TASK_STACK_TO_LEFT_OF: case TASK_STACK_TO_RIGHT_OF: mVertical = false; if (position == TASK_STACK_TO_LEFT_OF) { mWeight = weight; firstStack = stack; secondStack = mStack; } else { mWeight = 1.0f - weight; firstStack = mStack; secondStack = stack; } break; case TASK_STACK_GOES_ABOVE: case TASK_STACK_GOES_BELOW: mVertical = true; if (position == TASK_STACK_GOES_ABOVE) { mWeight = weight; firstStack = stack; secondStack = mStack; } else { mWeight = 1.0f - weight; firstStack = mStack; secondStack = stack; } break; } mFirst = new StackBox(mService, mDisplayContent, this); firstStack.mStackBox = mFirst; mFirst.mStack = firstStack; mSecond = new StackBox(mService, mDisplayContent, this); secondStack.mStackBox = mSecond; mSecond.mStack = secondStack; mStack = null; return stack; } </span>分裂的结果只有两种情况:
①分裂节点的StackBox.mStack转移到新的mFirst.mStack中,mSecond.mStack=new TaskStack(mService, stackId, mDisplayContent);
②分裂节点的StackBox.mStack转移到新的mSecond.mStack中,mFirst.mStack=new TaskStack(mService, stackId, mDisplayContent);
上面两种情况共同点是分裂节点StackBox.mStack会置null。
上述代码还可以归纳出,分裂节点就是二叉树的叶节点,只有叶节点才可以分裂,只有叶节点mStack变量才不为null。也可以说一个StackBox叶节点对应一个TaskStack。
从Android4.4源码来看,目前默认显示屏DEFAULT_DISPLAY的DisplayContent拥有两棵StackBox二叉树,这两个StackBox二叉树都还没有进行分裂过,只包含一个根节点。
8、TaskStack类
StackBox二叉树树的一个叶节点对应有一个TaskStack。
①TaskStack.mStackId,“stackId The id of the new TaskStack to create.”
②TaskStack.mTasks,保存着这个Task栈(TaskStack)中的所有Task。一个TaskStack中可以包含很多Task任务。
③TaskStack.mDimLayer
④TaskStack.mDimWinAnimator
⑤TaskStack.mAnimationBackgroundSurface
⑥TaskStack.mAnimationBackgroundAnimator