前言
本章我们继续上一节讲解 WMS 相关知识点,Window 是如何显示以及尺寸计算;
View 的添加过程
View 的添加过程是有两个地方,一个是在 onResume 的时候,一个是在
onResume
Activity 在创建之后,执行 onResume 的时候,把 View 添加到 WMS,然后由 WMS 交给 SurfaceFinger 进行绘制;
startActivity
在 startActivity 中的 startingWindow 的时候 也会有一个添加窗口的过程;
在 Window 的显示次序、窗口尺寸的计算,以及与 AMS 的通信等逻辑中有两个重要的概念,一个是 WindowContainerController 一个是 WindowContainer;我们来看下这两个重要的概念;
WindowContainer
/**
* Defines common functionality for classes that can hold windows directly or through their
* children in a hierarchy form.
* The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
* changes are made to this class.
*/
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {
}
可以看下它的定义:主要是用来实现 window 显示次序;它继承了 ConfigurationContainer 这个类,这个类主要是手机的一些设置,它也实现了 Comparable 接口,用来进行排序的,也就是控制显示次序;我们来看下它的 compareTo 方法的具体实现;
public int compareTo(WindowContainer other) {
if (this == other) {
return 0;
}
if (mParent != null && mParent == other.mParent) {
final WindowList<WindowContainer> list = mParent.mChildren;
return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
}
final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
try {
getParents(thisParentChain);
other.getParents(otherParentChain);
// Find the common ancestor of both containers.
WindowContainer commonAncestor = null;
WindowContainer thisTop = thisParentChain.peekLast();
WindowContainer otherTop = otherParentChain.peekLast();
while (thisTop != null && otherTop != null && thisTop == otherTop) {
commonAncestor = thisParentChain.removeLast();
otherParentChain.removeLast();
thisTop = thisParentChain.peekLast();
otherTop = otherParentChain.peekLast();
}
// Containers don't belong to the same hierarchy???
if (commonAncestor == null) {
throw new IllegalArgumentException("No in the same hierarchy this="
+ thisParentChain + " other=" + otherParentChain);
}
// Children are always considered greater than their parents, so if one of the containers
// we are comparing it the parent of the other then whichever is the child is greater.
if (commonAncestor == this) {
return -1;
} else if (commonAncestor == other) {
return 1;
}
// The position of the first non-common ancestor in the common ancestor list determines
// which is greater the which.
final WindowList<WindowContainer> list = commonAncestor.mChildren;
return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
? 1 : -1;
} finally {
mTmpChain1.clear();
mTmpChain2.clear();
}
}
当往 WindowContainer 放的时候,就会通过这个方法进行比较,来确定当前这个 window 要插入到什么位置;我们接着来看下 add 方法;
protected void addChild(E child, Comparator<E> comparator) {
if (!child.mReparenting && child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
+ " is already a child of container=" + child.getParent().getName()
+ " can't add to container=" + getName());
}
int positionToAdd = -1;
if (comparator != null) {
final int count = mChildren.size();
for (int i = 0; i < count; i++) {
// 在这里进行排序的逻辑
if (comparator.compare(child, mChildren.get(i)) < 0) {
positionToAdd = i;
break;
}
}
}
if (positionToAdd == -1) {
mChildren.add(child);
} else {
mChildren.add(positionToAdd, child);
}
// Set the parent after we've actually added a child in case a subclass depends on this.
child.setParent(this);
}
通过 comparator.compare(child, mChildren.get(i)) < 0 进行比较排序;
上图是 WindowContainer 的一些衍生类;
而 WindowContainer 又继承自 ConfigurationContainer,整体的一个关系图如下:
WindowContainerController
说完 WindowContainer 我们来说一下和它长的比较像的 WindowContainerController 先来上一张继承关系图
WindowContainer 和 WindowContainerController 之间的关系
系统把 Activity 等都抽象成了 WindowContainer 那么这些 container 需要一些显示逻辑,那么系统就把它们提取出一个 WindowContainerController 在这里面控制它;
就像上图的 Task 对应一个 TaskWindowContainerController,TaskStack 对应一个 StackWindowController;
整体的一个关系图就如下图:
通过上图可以看出 DisplayContent -> DisplayWindonwController -> ActivityDisplay -> ActivityRecord 等的这样的一个流程,那么我来看下 ActivityRecord 是怎么创建的;我们先来看下 ActivityDisplay
ActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
mSupervisor = supervisor;
mDisplayId = display.getDisplayId();
mDisplay = display;
mWindowContainerController = createWindowContainerController();
updateBounds();
}
这里调用了 createWindowContainerController 它在这里创建了 DisplayWindowController