5

目前,我正在尝试一个非常简单的 GUI 绘图......“引擎”(我想你可以这么称呼它)。它的要点:

  1. 有一个 FrontController 被用户请求击中;每个请求都有一个uid
  2. 每个uid(读作“页面”)都有其上存在的组件(“模块”)的声明
  3. 组件是Sprite的子类,本质上是唯一的

自然,我需要一种隐藏/显示这些精灵的方法。目前,我拥有它就像 Flex 默认拥有它一样 - 方式是“如果我们在一个 comp 可见的地方,创建它,缓存它并在每次它再次可见时重用它”。

问题是——这将是更合适和更有效的隐藏和显示方式——通过addChild/removeChild或切换visible

我的看法是:

  • visible又快又脏(在第一次测试中)
  • visible不会创建一连串冒泡事件,例如Event.ADDEDEvent.REMOVED
  • 不可见的组件不会获得鼠标事件

当我removeChild确定组件将不再需要在屏幕上时(或者缓存太大,例如),我会调用它

stackoverflow'ers / AS3-crazy 的人是怎么想的?

更新:这是一本很好的读物(忘记了谷歌)。

我会坚持visible; 它似乎更适合我的任务;Adobe 的手册“优化 FLASH 平台的性能”,第 15 页。69给了我更多的信心。

这是我为感兴趣的人测试的代码片段:

package 
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.utils.getTimer;

/**
 * Simple benchmark to test alternatives for hiding and showing
 * DisplayObject.
 * 
 * Use:
 * <code>
 * new DisplayBM(stage);
 * </code>
 * 
 * Hit:
 * - "1" to addChild (note that hitting it 2 times is expensive; i think
 * this is because the player has to check whether or not the comp is
 * used elsewhere)
 * - "q" to removeChild (2 times in a row will throw an exception) 
 * - "2" to set visible to true
 * - "w" to set visible to false
 * 
 * @author Vasi Grigorash
 */    
public class DisplayBM{
    public function DisplayBM(stage:Stage){
        super();

        var insts:uint = 5000;
        var v:Vector.<Sprite> = new Vector.<Sprite>(insts);
        var i:Number = v.length, s:Sprite
        while (i--){
            s = new Sprite;
            s.graphics.beginFill(Math.random() * 0xFFFFFF);
            s.graphics.drawRect(
                Math.random() * stage.stageWidth, 
                Math.random() * stage.stageHeight,
                10, 
                10
            );
            s.graphics.endFill();
            v[i] = s;
        }

        var store:Object = {};
        store[Event.ADDED] = null;
        store[Event.REMOVED] = null;
        var count:Function = function(e:Event):void{
            store[e.type]++;
        }
        var keydown:Function = function (e:KeyboardEvent):void{
            var key:String
            //clear event counts from last run
            for (key in store){
                store[key] = 0;
            }

            stage.addEventListener(Event.ADDED, count);
            stage.addEventListener(Event.REMOVED, count);

            var s0:uint = getTimer(), op:String;
            var i:Number = v.length;
            if (e.keyCode === Keyboard.NUMBER_1){
                op = 'addChild';
                while (i--){
                    stage.addChild(v[i]);
                }
            }
            if (e.keyCode === Keyboard.Q){
                op = 'removeChild';
                while (i--){
                    stage.removeChild(v[i]);
                }
            }
            if (e.keyCode === Keyboard.NUMBER_2){
                op = 'visibile';
                while (i--){
                    v[i].visible = true;
                }
            }
            if (e.keyCode === Keyboard.W){
                op = 'invisibile';
                while (i--){
                    v[i].visible = false;
                }
            }
            if (op){
                //format events
                var events:Array = [];
                for (key in store){
                    events.push(key + ' : ' + store[key])
                }

                trace(op + ' took ' + (getTimer() - s0) + ' ' + events.join(','));
            }

            stage.removeEventListener(Event.ADDED, count);
            stage.removeEventListener(Event.REMOVED, count);
        }

        //autodispatch
        stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
    }
}
}
4

3 回答 3

2

Visible 对我来说更有意义(因为删除一个孩子表示一个终结),并且是我在自己的项目中显示/隐藏时倾向于使用的。

我还假设 addChild 的性能稍差,但我没有做过任何测试。

编辑:我刚刚看到这篇 Adob​​e 文章http://help.adobe.com/en_US/as3/mobile/WS5d37564e2b3bb78e5247b9e212ea639b4d7-8000.html它指定在使用 GPU 渲染模式时只需设置 visible = false 就会产生性能影响是绘制重叠对象的成本(即使它们不可见)。相反,建议完全移除孩子:

尽可能避免过度绘制。过度绘制是将多个图形元素分层,以使它们相互遮蔽。使用软件渲染器,每个像素只绘制一次。因此,对于软件渲染,无论有多少图形元素在该像素位置相互覆盖,应用程序都不会导致性能损失。相比之下,硬件渲染器为每个元素绘制每个像素,无论其他元素是否遮挡了该区域。如果两个矩形相互重叠,则硬件渲染器将重叠区域绘制两次,而软件渲染器仅绘制一次该区域。

因此,在使用软件渲染器的桌面上,您通常不会注意到过度绘制对性能的影响。但是,许多重叠的形状会对使用 GPU 渲染的设备的性能产生不利影响。最佳做法是从显示列表中删除对象,而不是隐藏它们。

于 2012-04-05T23:28:58.873 回答
1

删除子项可以更好地减少实例、事件并从您的 Flash 电影中释放内存,您可能会发现经过一段时间后精灵可能会相互影响。从它们的绘制方式或那里的侦听器来看,当此方法使用时,垃圾收集通常会发挥作用最终可以与您的应用程序一起实施

Visible 仍然在内存中有精灵,它只是当前没有绘制。您也可以保存精灵然后删除它,然后在需要时重新加载它,这将是所有解决方案的理想选择。使用数组存储数据是另一种解决方案,也取决于您的应用程序是如何实现的,很难说,因为我们不知道,哈哈

添加孩子的表演我会说压力较小,因为它仍然是唯一添加的项目与隐藏的倍数。此外,在这些隐藏的孩子中,属性与听众一起存储在内存中。

于 2012-04-06T03:14:34.503 回答
0

以下是 Moock 关于该主题的一些硬数据:http: //www.developria.com/2008/11/visible-false-versus-removechi.html

                  Children on the                     Single-frame 
                  Display List    .visible   .alpha   Elapsed Time (ms)
No Children       0               --         --       4
Non-visible       1000            false      1        4
Zero Alpha        1000            true       0        85
Fully Visible     1000            true       1        1498
90% Transparent   1000            true       .1       1997
于 2013-07-24T00:07:07.547 回答