巧用Event.RENDER优化Flash渲染效率

在Flash或Flex开发中,我们经常需要操作可视化的显示对象(有可能是普通的Sprite或MovieClip,也可能是更复杂的Flex Component),我们可能需要不停的设置它们的尺寸或位置,而且这样的设置代码可能会分散在我们的类的各个方法里面。注意观察您是否发现,在同一次代码执行过程中,我们会有重复性的设置工作,比如在某一个方法里设置了组件的宽度,然后在另外一个验证方法里马上又改变了这个组件的宽度。注意对显示对象的属性设置,显然要比更改一个普通对象的属性会引起更高的消耗。这样没有必要的重复性设置,如果量很大,就可能对我们应用的性能造成影响。

另一种情况是,我们设置了组件的尺寸或其它显示属性,但不希望每一次设置都对组件直接产生影响,而希望以一种合并执行的方式,这种方式显然更符合我们的期望,也可以降低一些计算量。比如我们要在组件的尺寸发生变化之后,重新绘制背景,那么我们可能先设置组件的宽度,然后设置组件的高度(或者反过来,或者只设置一个,就像下面一行代码展示的),但我们不希望每次操作都反映到组件的改变,而是缓存起来,等待下一次渲染列表更新的时候,执行渲染操作。

header.width = stage.stageWidth;
header.height = stage.stageHeight;
复制代码
如果我们不考虑性能优化,那么常规思路就是,重写width和height的getter和setter,然后在每一次设置里都调用一下绘制背景的方法,这样保证无论是单独设置宽度或高度,或者都设置,都可以让背景得以重新绘制。如下面的代码所示:


package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
measure();
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
measure();
}
public function Header()
{
super();
}
//绘制背景的方法
private function measure():void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
}
}
}
普通浏览复制代码保存代码打印代码
package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
measure();
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
measure();
}
public function Header()
{
super();
}
//绘制背景的方法
private function measure():void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
}
}
}package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
measure();
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
measure();
}
public function Header()
{
super();
}
//绘制背景的方法
private function measure():void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
}
}
}
这样的代码实现,当然是可以正常工作的,但您或许也注意到了其中存在可能重复性的执行工作。如果我们同时设置了宽度和高度,实际上绘制背景的方法被执行了两次。这只是一个简单的例子,多余的操作显然没有产生多大的影响,但防患于未然,我们是否可以优化这个操作呢?

借助于Event.RENDER事件,我们可以将属性的变更推迟到下一次渲染。思路就是,当宽度或高度改变,我们不立即触发绘制背景的方法,而是加以标记,并侦听Event.RENDER事件,在下一次渲染的时候会执行回调方法,完成背景绘制。优化后的代码:


package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
private var _needUpdate:Boolean = false;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
needUpdate = true;
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
needUpdate = true;
}
public function get needUpdate():Boolean
{
return _needUpdate;
}
public function set needUpdate(value:Boolean):void
{
if(_needUpdate == value) return;
_needUpdate = value;
if(_needUpdate) {
addEventListener(Event.RENDER,measure);
if(stage != null) stage.invalidate();
} else {
removeEventListener(Event.RENDER,measure);
}
}
public function Header()
{
super();
}
private function measure(...args):void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
needUpdate = false;
}
}
}
普通浏览复制代码保存代码打印代码
package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
private var _needUpdate:Boolean = false;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
needUpdate = true;
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
needUpdate = true;
}
public function get needUpdate():Boolean
{
return _needUpdate;
}
public function set needUpdate(value:Boolean):void
{
if(_needUpdate == value) return;
_needUpdate = value;
if(_needUpdate) {
addEventListener(Event.RENDER,measure);
if(stage != null) stage.invalidate();
} else {
removeEventListener(Event.RENDER,measure);
}
}
public function Header()
{
super();
}
private function measure(...args):void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
needUpdate = false;
}
}
}package com.riameeting.fingerchart.mobile.view
{
import flash.display.Sprite;
import flash.events.Event;
public class Header extends Sprite
{
private var _width:Number;
private var _height:Number;
private var _needUpdate:Boolean = false;
override public function get width():Number
{
return _width;
}
override public function set width(value:Number):void
{
if(_width == value) return;
_width = value;
needUpdate = true;
}
override public function get height():Number
{
return _height;
}
override public function set height(value:Number):void
{
if(_height == value) return;
_height = value;
needUpdate = true;
}
public function get needUpdate():Boolean
{
return _needUpdate;
}
public function set needUpdate(value:Boolean):void
{
if(_needUpdate == value) return;
_needUpdate = value;
if(_needUpdate) {
addEventListener(Event.RENDER,measure);
if(stage != null) stage.invalidate();
} else {
removeEventListener(Event.RENDER,measure);
}
}
public function Header()
{
super();
}
private function measure(...args):void
{
graphics.clear();
graphics.beginFill(0xCCCCCC,1);
graphics.drawRect(0,0,width,height);
graphics.endFill();
trace("draw complete");
needUpdate = false;
}
}
}
如果您也从事Flex开发,那么应该了解到在Flex的组件设计中已经应用了这种实施模式,以便让结构复杂的Flex组件尽可能的获取更好的渲染效率。比如Flex组件的callLater事件,就是这个思路。您可以查阅Flex文档了解这方面的信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值