这里注意指向父控件节点的parent和指向子控件节点的children的定义的差别,children指向的是ViewNode类型的列表。为什么会这样呢?其实很简单:父亲只有一个,儿子可以有多个。
有了这些做为铺垫后,我们就可以往回看上面“代码14-8-4 BridgeDevice - parseViewHierarchy”430行中创建一个ViewNode的过程了:
currentNode = new ViewNode(window, currentNode, line.substring(depth));
代码14-8-7 BridgeDevice-parseViewHierarchy-创建ViewNode
我们进入到ViewNode的构造函数:
119 public ViewNode(Window window, ViewNode parent, String data)
120 {
121 this.window = window;
122 this.parent = parent;
123 this.index = (this.parent == null ? 0 : this.parent.children.size());
124 if (this.parent != null) {
125 this.parent.children.add(this);
126 }
127 int delimIndex = data.indexOf('@');
128 if (delimIndex < 0) {
129 throw new IllegalArgumentException("Invalid format for ViewNode, missing @: " + data);
130 }
131 this.name = data.substring(0, delimIndex);
132 data = data.substring(delimIndex + 1);
133 delimIndex = data.indexOf(' ');
134 this.hashCode = data.substring(0, delimIndex);
135
136 if (data.length() > delimIndex + 1) {
137 loadProperties(data.substring(delimIndex + 1).trim());
138 }
139 else {
140 this.id = "unknown";
141 this.width = (this.height = 10);
142 }
143
144 this.measureTime = -1.0D;
145 this.layoutTime = -1.0D;
146 this.drawTime = -1.0D;
147 }
代码 14-8-8 ViewNode-构造函数
整个构造函数主要做的事情其实差不多都跟传进来的ViewServer返回的一行控件信息有关系,基本上都是去解析这个字串然后去赋予ViewNode相应的属性给保存起来:
- 121-122行: 首先把传进来的代表整个屏幕最上层的获得焦点的窗口Window实例和本控件节点的父节点给保存起来
- 124-126行: 如果当前新创建的这个ViewNode实例不是根控件节点,那么把自己加入到父控件的children这个列表里面,让父控件可以找到自己
- 127-134行: 从控件字串信息中解析出控件名和其对应的哈希值并保存起来。这些信息是在该控件信息行的最前面,并且是用@这个符号给分开的,大家不记得话请返回去查看” 图13-6-1 NotesList控件列表”了,这里列出其中一个做为例子”android.widget.FrameLayout@41901ab0”
- 137行:调用ViewNode自身的成员方法loadProperties来解析控件字串剩余的属性。
那么我们就往下看下剩余的控件属性是怎么给解析出来的,loadProperties这个方法有点长,我们把它分看来慢慢分析,先看第一部分:
168 private void loadProperties(String data) {
169 int start = 0;
170 boolean stop;
171 do {
172 int index = data.indexOf('=', start);
173 Property property = new Property();
174 property.name = data.substring(start, index);
175
176 int index2 = data.indexOf(',', index + 1);
177 int length = Integer.parseInt(data.substring(index + 1, index2));
178 start = index2 + 1 + length;
179 property.value = data.substring(index2 + 1, index2 + 1 + length);
180
181 this.properties.add(property);
182 this.namedProperties.put(property.name, property);
183
184 stop = start >= data.length();
185 if (!stop) {
186 start++;
187 }
188 } while (!stop);
...
}
代码14-8-9 ViewNode-loadProperties-获取控件属性