callLater解析

 

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

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

1button.width=200;
2button.height=28;
3button.setStyle("textFormat",myTextFormat);

 

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

1button.width=200;
2button.height=28;
3button.setStyle("textFormat",myTextFormat);
4button.redraw();

 

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

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

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

  • commitProperties()
  • measure()
  • updateDisplayList()

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

    01package com.colorhook.tools{
    02   
    03    /**
    04     *  @author colorhook
    05     * @copyright http://www.colorhook.com
    06     */
    07   
    08     import flash.display.DisplayObject;
    09     import flash.utils.Dictionary;
    10     import flash.events.Event;
    11   
    12    public class FrameCallLater implements ICallLater{
    13   
    14        private var _target:DisplayObject;
    15        private var methods:Dictionary;
    16        private var inCallLaterPhase:Boolean=false;
    17   
    18        public function FrameCallLater(target:DisplayObject){
    19            this._target=target;
    20            methods=new Dictionary(true);
    21            super();
    22        }
    23   
    24        /**
    25         * defined by ICallLater, I write a class TimeCallLater to implement it also.
    26         */
    27        public function call(fun:Function):void{
    28            if (inCallLaterPhase||_target==null) { return; }
    29   
    30            methods[fun]=true;
    31   
    32            if (_target.stage != null) {
    33                _target.stage.addEventListener(Event.RENDER,callLaterDispatcher,false,0,true);
    34                _target.stage.invalidate();
    35            } else {
    36                _target.addEventListener(Event.ADDED_TO_STAGE,callLaterDispatcher,false,0,true);
    37            }
    38        }
    39   
    40        private function callLaterDispatcher(event:Event):void {
    41            if (event.type == Event.ADDED_TO_STAGE) {
    42                _target.removeEventListener(Event.ADDED_TO_STAGE,callLaterDispatcher);
    43                _target.stage.addEventListener(Event.RENDER,callLaterDispatcher,false,0,true);
    44                _target.stage.invalidate();
    45                return;
    46            } else {
    47                event.target.removeEventListener(Event.RENDER,callLaterDispatcher);
    48                if (_target.stage == null) {
    49                    _target.addEventListener(Event.ADDED_TO_STAGE,callLaterDispatcher,false,0,true);
    50                    return;
    51                }
    52            }
    53   
    54            inCallLaterPhase = true;
    55   
    56            for (var method:Object in methods) {
    57                method();
    58                delete(methods[method]);
    59            }
    60            inCallLaterPhase = false;
    61        }
    62   
    63        public function get target():DisplayObject{
    64            return _target;
    65        }
    66   
    67    }
    68}
    *****************************************************

    找了很久的资料,才解决tree加载时显示所有节点这个问题,引自http://hi.baidu.com/lz0830/blog/item/7b406e82d7f41c98f703a632.html

    该文中提出Tree的数据源在MXML文件中和数据源是从后台程序获取两种情况:

    一、针对第一种情况(tree的数据源在MXML文件中)的写法:

    private function initApp():void {
         
    for each(var item:XML in this.myTree.dataProvider)
               this.myTree.expandChildrenOf(item,true);

    }

    该函数的调用creationComplete="initApp()"

     

    二、数据源从后台程序获取

    <!--  读取xml文件给tree绑定数据源 -->
    <mx:HTTPService id="tree_httpsrv" url="assets/data/treeview.xml"  result="setTree(event)" fault="faultOperation(event)"  resultFormat="xml" />

    <!-- 读取xml文件的处理  -->

    [Bindable]
    private var tree_xml:XML;

    private function setTree(event:ResultEvent):void
    {
           tree_xml = XML(event.result);
           var tree_data:XMLList = tree_xml.treeviewNode;
           myTree.dataProvider = tree_data;
           myTree.callLater(expandTree);
    }

    private function expandTree():void
    {
           //expand all tree node
           myTree.expandChildrenOf(tree_xml,true);
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值