FLEX组件的失效机制由
IInvalidating ILayoutManagerClient和 实现了ILayoutManager的LayoutManager 以及UIComponent中的commitProperties()、measure()、updateDisplayList()完成 IInvalidating 接口定义了 invalidateProperties、 invalidateSize、 invalidateDisplayList、 validateNow。 ILayoutManagerClient 接口定义了 validateProperties、 validateSize、 validateDisplayList ILayoutManager 接口定义的主要方法有 invalidateProperties、 invalidateSize、 invalidateDisplayList、 validateNow、 validateClient方法 名字看上去跟IInvalidating 接口的一样 区别在于ILayoutManager 的方法有一个ILayoutManagerClient参数需要传入 下面来说一下 他们是怎么协调工作并达到延迟更新组件的效果 以Label组件更改text属性为例当设置text属性之后代码的执行 我按代码执行顺序来说 |
喜欢0
|
沙发#
发布于:2013-01-31 15:22
Label组件
首先 1、Label组调用IInvalidating接口中的invalidateProperties方法 2、在invalidateProperties中程序会调用layoutManager的invalidateProperties并将自身传入 3、layoutManager将label加入到invalidatePropertiesQueue这个优先队列里面(layoutManager弟213行)关于属性部分到这里暂时结束了 然后 1、Label组件调用IInvalidating接口中invalidateSize方法 2、在invalidateSize方法中程序会调用layoutManager的invalidateSize并将自身传入 3、layoutManager将label加入到invalidateSizeQueue这个优先队列里面(layoutManager弟236行)关于属性组件size到这里暂时结束了 最后 1、Label组件调用IInvalidating接口中invalidateDisplayList方法 2、在invalidateDisplayList方法中程序会调用layoutManager的invalidateDisplayList并将自身传入 3、layoutManager将label加入到invalidateDisplayListQueue这个优先队列里面(layoutManager弟259行)关于属性组件的布局和绘制到这里暂时结束了 | |
板凳#
发布于:2013-01-31 15:23
当Label组件的这些操作做完之后 屏幕上呈现出来的画面并没有改变
因为layoutManager将这些更改延迟到了下一次屏幕更新的时候 当layoutManager的invalidate系列方法被调用的时候 layoutManager都会检测自己是否添加了Event.ENTER_FRAME事件 (参见LayoutManager弟450、501、538行)如果没有添加会马上添加上 , 当下一次屏幕更新到来的时候 1、LayoutManager会调用doPhasedInstantiationCallback(1168行)方法也就是 Event.ENTER_FRAME的handler 2、然后在再调用doPhasedInstantiation函数(777行) 3、doPhasedInstantiation函数会按顺序执行LayoutManager 的 validateProperties(571行)、 validateSize(642行)、 validateDisplayList(713行)3个方法,(程序会进行一些判断) 大家应该还记得在Label组件在调用layoutManager的invalidate系列方法的时候会将自身传入也就是传入了一个ILayoutManagerClient 接口而LayoutManager 会将其存入一个优先队列中 所以现在 当LayoutManager 调用在自己的 validateProperties、validateSize、validateDisplayList方法的时候 这3个函数会分别从对应的优先队列中取出ILayoutManagerClient 对象并调用他们的validateProperties、validateSize、validateDisplayList方法 | |
地板#
发布于:2013-01-31 15:23
上面说到了优先队列 所以这些优先队列中对象的函数调用肯定会有一个顺序的问题 在说这个顺序之前先说一下FLASH的显示列表... FLASH的显示对象由displayobject而来 而displayObjectContainer是显示对象的容器 FLASH的显示列表使用Composite模式创建 看到这个模式首先想到的应该是一个树形结构 在这个树形结构中displayObjectContainer做为树的非叶子节点displayobject为叶子节点 stage对象是一个displayObjectContainer是一个根节点 举个例子 舞台上有一个Sprite和一个Container然后Container里面有一个Shape一个Bitmap一个Sprite 这样他们的关系就是 stage |- > Sprite |- > Container |- >Shape |- > Bitmap | - > Sprite 从上面的关系可以知道 有了这个树形结构就很容易设置他们的深度 ,至于这个树形结构的其他用途暂时不去考虑 而ILayoutManagerClient 正是通过这个树形结构设置了每个组件的nestLevel属性 这个属性被优先队列用来排序 说到这里 排序的问题OK了 继续说validateProperties、validateSize、validateDisplayList这3个方法 他们的顺序分别是 validateProperties 是自上而下的 (可能是考虑到父组件会改变子组件的属性) validateSize 是自下而上的(自组件的大小会影响到父组件 很多组件在测量阶段都会用到子组件的size) validateDisplayList是自上而下(一层盖一层) 上面说道这3个函数会分别从对应的优先队列中取出ILayoutManagerClient 对象并调用他们的validateProperties、validateSize、validateDisplayList方法 在实现了ILayoutManagerClient接口的组件中 这个3个方法又分别调用了 commitProperties()、measure() 、 updateDisplayList() 而这3个方法就是我们自定义组件时候最常用的3个方法 其中measure方法比较特殊 它是用来设计默认大小的 一旦你为组件显示的指定了大小这个函数就不会再执行 即使调用了invalidateSize方法也不会执行 | |
4楼#
发布于:2013-01-31 15:23
总结:
自定义显示组件的时候 影响到组件显示状态的属性 要在set里面调用invalidateProperties方法 然后在commitProperties方法里面验证属性的正确性如果不正确设置一个新的值 例如 设置的宽度小于组件的最小宽度 如果小于就设置为最小宽度 然后再调用invalidateDisplayList方法 在updateDisplayList中进行组件的绘制布局 在updateDisplayList不要用height width属性 一定要用unscaledWidth unscaledHeight因为你无法确定组件是否被用户缩放 所以用没有缩放的宽高比较靠谱 |