cacheAsBitmap(转)

*********************************************************

cacheAsBitmap这个属性很多人都知道,但少有人明白它到底是如何生效的。虽然看名字是转换为位图处理,但用起来的时候感觉却也不是如此。所以,不少人最终选择自己转换Bitmap。
当然,自己转Bitmap也是可以的,也只是多浪费点内存和处理速度,然后麻烦点罢了。但事实上,很多时候cacheAsBitmap已经足够使用了。
先得说说FLASH的屏幕更新机制。在Debug播放器内,可以勾选显示重复区域来以红框显示更新区域。也就是说,FLASH并不会每帧都渲染所有的区域。这点上的确如此。但是在红框内呢?比如我有一张很复杂的静态矢量图在背景上,然后上面显示了一个很简单的动画(甚至是一个透明的不断重刷的矩形),以通常的想法,FLASH应该缓存背景的图像,仅仅是重新更新上面的图形,但事实上并不会这样。FLASH才不管你哪些动哪些不动,只要是红框内的图形,它一定都会重新刷新一次,如果不解决这个问题,根本没法做“全屏”的东西,因为哪怕你空刷一个占满屏幕的Bitmap都会导致所有的矢量图全部更新。
事实上,cacheAsBitmap就是用来解决这个问题的。你可以理解成它能够影响FLASH的渲染机制。只要一个显示对象被设为 cacheAsBitmap,除了他自己之外,外部将无法令其重新刷新,而是像我们想象的那样简单的叠加。当然,副作用是,被设置为 cacheAsBitmap的图形,内部只要变了一点,哪怕是很小的区域,也会导致整个对象更新,但是,也只有这种情况才会更新。
除此之外,还有以下的影响:
它相当于被设置为layer混合,混合关系会出现问题(诸如Alpha混合)。
由于实现方式是缓存位图,会遇到整数坐标问题。所以,平移和缩放都会一顿一顿的,此外影响到的还有设备文本。好在设备文本也可以设置为 cacheAsBitmap,这样就和外部容器一起“顿”,就看不出来了。
此外,我发现这种做法还会影响到Draw的区域。这点我还没认真测试过。
cacheAsBitmap是有效的。我们觉得它没有效果,可能是因为把这个设置放在了动画上(动画是一直动的),或者设置在了运动的物品外部(内部物品运动外部不动的话,可能还比原来更慢)。其实我们大可以自己尝试,一般来说,只要别出现显示上的问题,在非容器对象设置cacheAsBitmap都会有一定的性能提升。而且它并不像自己实现的Bitmap,缓存位图并没有消耗多余的性能,而且也不可能出现内存泄漏。
最好不要把它当作缓存位图,而是当成一种改变FLASH渲染机制的手段。cacheAsBitmap具有两面性,错误的设置也可能会更慢。当然,它是个运行期间属性,有心的话,也可以动态修改。

*********************************************************

当在一个容器中有很多个分别独立的对象,他们在移动或各自做形变时,Flash Player需要不停的对这些单独区域进行重新绘制,
导致重绘占用了大量的cpu时间。这时可以把容器的cacheAsBitmap设为true,这时Flash Player 将缓存显示对象的内部位图表示形式,
这样就好像我们并没有把那么多显示对象添加到容器中,而是像位图处理一样把这些对象逐个draw到BitmapData上(draw前lock,结束后unlock),完成后在统一重绘这张位图。这样重绘每个对象的时间转会成了重绘一张位图。不过这里是会进行像素紧贴的,所以就不会有小数级的控制了。
当对象非常多的时候,我们会发现效率的提升是非常高的。
比如我们最原始做List组件的方法,是使用一个矩形的遮罩,遮盖住需要显示的item范围上,滚动条滚动时改变容器的y坐标,
当只有四五十个item的时候还行,如果数量很多的时候,打开你的任务管理器就会发现,只要一滚动List,cpu就会升的非常高,
甚至的占据了一个核。
改进的方法是使用DisplayObject的scrollRect来进行滚动,然后开启cacheAsBitmap,然后就会看到一个性能上的惊喜。

*********************************************************

默认情况下cacheAsBitmap属性为false。开启cacheAsBitmap的最通俗易懂的作用就是拿内存换cpu。使用cacheAsBitmap有以下可以注意的几点:
    1.如果显示对象无需alpha,那么opaqueBackground于cacheAsBitmap配合使用可以很好控制呈现的性能。
    2.不要将整个场景进行cacheAsBitmap设置,它反而会降低你的程序性能。
    3.cacheAsBitmap不是万能的,当你的程序对原有的内容进行像素位的改动时,会降低它的作用。这些改动包括,旋转,缩放,更改alpha值等改变它原有像素的举动。
    4.在fp10中一个bitmapdata可以被多个bitmap引用,所以同样原始数据的对象,可以引用同一个父,在不同的对象引用中设置cacheAsBitmap,他们之间可以复用缓存。

    附件是对cacheAsBitmap做了一个简单的测试,用于验证我所提出的以上几点。
    在此测试代码中,被注释掉的代码将一点点部分的开启,来验证我刚刚所说的那几点。此代码中我故意将ENTER_FRAME事件给每个子类分发。这里可以改成主程序来用统一的一个ENTER_FRAME来进行图片的移动。这不在篇文章的范畴之内,所以不进行考虑。
    实验1,不对代码做任何修改直接运行。我的机器cpu占用率显示在70%-75%之间,内存消耗13000k之间。
    实验2,开启bitmapApple.cacheAsBitmap=true代码。cpu占用在25%-33%之间,内存消耗26000k之间。
    实验3,同时开启bitmapApple.opaqueBackground=0xff于bitmapApple.cacheAsBitmap=true代码。cpu占用在20%-25%之间,内存消耗27000k之间。
    实验4,开启holder.cacheAsBitmap=true代码,cpu占用70%-78%之间,内存消耗21000k之间。
    实验5,开启bitmapApple.cacheAsBitmap=true于alpha = Math.random()代码,cpu占用55%-57%之间,内存消耗26000k之间。
    从以上实验结果可以证明,上边所说的那几点cacheAsBitmap的特点同实验数据吻合。

posted @ 2011-08-26 16:01  Do.else  阅读(1505)  评论(1编辑  收藏  举报