• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Games Fantasy
博客园    首页    新随笔    联系   管理    订阅  订阅
Flash & Flex组件优化的杀手锏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{
     
    	/**
    	 *	@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;
    		}
     
    	}
    }
    
  • posted on 2010-03-16 21:17  ╰洛つ☆泺oO  阅读(1339)  评论(0)    收藏  举报
    刷新页面返回顶部
    博客园  ©  2004-2025
    浙公网安备 33010602011771号 浙ICP备2021040463号-3