Flex\flash中的callLater()函数作用

Flash的fl组件和Flex的mx组件都有一个受保护方法callLater,callLater可以说是优化组件执行效率的一个杀手锏,极其有用。

拿Flash的fl组件为例,fl组件有个重绘方法redraw(),如果改变组件的大小,焦点的获得和丢失都会是组件重绘来呈现不同的状态。而组件是复杂的,重绘的开销很大。如果假想一个按钮执行以下程式来更改外观,并且每次的更改都触发redraw()方法执行,那它将执行3次重绘,很显然是不须要的。

button.width=200;
button.height=28;
button.setStyle("textformat",mytextformat);

一个优化的方式是假设组件不会自动重绘,需要手动进行:

button.width=200;
button.height=28;
button.setStyle("textformat",mytextformat);
button.redraw();

这个方式不太友好,每次都要记得去重绘组件,幸运的是callLater解决了这个问题。

callLater把要执行的函数延迟到下一帧。所以对button的width更改后,它会记得在下一帧重绘自身,当然这一帧你还改变了height和样式,它也只是重复地记忆要在下一帧重绘自身。到了下一帧的时候,它执行一次redraw(),仅是一次。

Flex组件的基类UIComponent有110多个公开属性,90个公开方法,17个受保护方法,70多个事件,10多个样式,10多个效果,还有6个常量。一个基类都如此庞大,可想而知,优化是多么重要。
在Flex组件的callLater中,重绘被分割成了三个受保护的方法
# commitProperties()
# measure()
# updatedisplayList()

职责的分割更加提高了效率,这些延迟执行都是callLater实现的。把callLater实现的细节抽取下来写成一个单独的类:

package com.colorhook.tools{ 
     import flash.display.displayObject;
     import flash.utils.Dictionary;
     import flash.events.Event;
 
    public class FrameCallLater implements ICallLater{
 
        private var _target:displayObject;
        private var methods:Dictionary;
        private var inCallLaterPhase:Boolean=false;
 
        public function FrameCallLater(target:displayObject){
            this._target=target;
            methods=new Dictionary(true);
            super();
        }
 
        /**
         * defined by ICallLater,I write a class TimeCallLater to implement it also.
         */
        public function call(fun:Function):void{
            if (inCallLaterPhase||_target==null) { return; }
 
            methods[fun]=true;
 
            if (_target.stage != null) {
                _target.stage.addEventListener(Event.RENDER,callLaterdispatcher,false,true);
                _target.stage.invalidate();
            } else {
                _target.addEventListener(Event.ADDED_TO_STAGE,true);
            }
        }
 
        private function callLaterdispatcher(event:Event):void {
            if (event.type == Event.ADDED_TO_STAGE) {
                _target.removeEventListener(Event.ADDED_TO_STAGE,callLaterdispatcher);
                _target.stage.addEventListener(Event.RENDER,true);
                _target.stage.invalidate();
                return;
            } else {
                event.target.removeEventListener(Event.RENDER,callLaterdispatcher);
                if (_target.stage == null) {
                    _target.addEventListener(Event.ADDED_TO_STAGE,true);
                    return;
                }
            }
 
            inCallLaterPhase = true;
 
            for (var method:Object in methods) {
                method();
                delete(methods[method]);
            }
            inCallLaterPhase = false;
        }
 
        public function get target():displayObject{
            return _target;
        }
 
    }
}

相关文章

一:display:flex布局display:flex是一种布局方式。它即可以...
1. flex设置元素垂直居中对齐在之前的一篇文章中记载过如何...
移动端开发知识点pc端软件和移动端apppc端软件是什么,有哪些...
最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周...
display:flex;把容器设置为弹性盒模型(设置为弹性盒模型之后...
我在网页上运行了一个Flex应用程序,我想使用Command←组合键...