zoukankan      html  css  js  c++  java
  • Flash & Flex组件优化的杀手锏callLater

    Flash & Flex组件优化的杀手锏callLater

    最近使用flexlib,看源码的时候发现有大量的 calllater() 方法,搜了搜 原来如此:

    原帖:http://www.colorhook.com/blog/?p=216

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

    拿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{
     
        /**
         *    @author colorhook
         * @copyright http://www.colorhook.com
         */
     
         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,0,true);
                    _target.stage.invalidate();
                } else {
                    _target.addEventListener(Event.ADDED_TO_STAGE,callLaterDispatcher,false,0,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,callLaterDispatcher,false,0,true);
                    _target.stage.invalidate();
                    return;
                } else {
                    event.target.removeEventListener(Event.RENDER,callLaterDispatcher);
                    if (_target.stage == null) {
                        _target.addEventListener(Event.ADDED_TO_STAGE,callLaterDispatcher,false,0,true);
                        return;
                    }
                }
     
                inCallLaterPhase = true;
     
                for (var method:Object in methods) {
                    method();
                    delete(methods[method]);
                }
                inCallLaterPhase = false;
            }
     
            public function get target():DisplayObject{
                return _target;
            }
     
        }
    }

  • 相关阅读:
    组合数取模的题……
    对组合数取模
    n!(n的阶乘)
    八、元素绑定
    七、Application类
    RC振荡电路
    运算放大器工作原理
    No
    合并查询结果
    连接查询
  • 原文地址:https://www.cnblogs.com/jiahuafu/p/1674325.html
Copyright © 2011-2022 走看看