【问题标题】:as3 if remove Parent Do all children get removed too?as3 if remove Parent 是否所有的孩子也会被移除?
【发布时间】:2013-05-18 07:14:48
【问题描述】:

我正在将一个名为 Spiri 的 mc 加载到一个名为 Box 的 mc 中。后来我想从内存使用和屏幕外删除。我在此处未显示补间中的屏幕外。

如果我使用removeChild(box);,它还会删除所有带有 in 的子项吗? 基本上我正在使用函数调用从库中加载 3 部电影。然后尝试删除它们并多次调用相同的函数。这意味着相同的电影以相同的名称一次又一次地加载。这应该替换旧的,但可能不是因为我没有正确删除它们,因为到第 10 次或第 15 次调用它变得非常慢。

我也在一个函数中添加了一个事件监听器。那是不是每次都添加一些事件列表器并占用资源?

多次运行该函数后似乎很慢,这让我相信某些东西没有正确卸载。

//I tried 
box.removeChild(Spiri);
Spiri = null;
//then remove the parent like this
removeChild(box);  /// but this gets an error.
again if i just do this
removeChild(Spiri); // it makes me wondering if they are getting removed.

如何删除 mc 中的父级和所有子级的最佳方法是什么?

【问题讨论】:

  • 我建议你看看 Adob​​e Scout 我相信它暂时仍然是免费的,并且是一个用于分析和调整性能的惊人工具。它将监视计算机上的活动 SWF 文件,或者您可以在移动设备上安装 Scout 并配置 AIR 应用程序(设置非常简单)。
  • @shaunhusain 同意 Adob​​e Scout。老实说,我现在无法想象没有它的 Flash 开发。如此出色的应用程序。
  • 这里还有一些好东西:active.tutsplus.com/tutorials/workflow/… 还要检查的另一件事是 MrDoobs HiRes Stats github.com/mrdoob/Hi-ReS-Stats
  • @shaunhusain 我实际上构建了自己的显示器,它可以像 Hi-Res 一样显示在应用程序中。监控内存、每秒帧数,甚至还有一个内置控制台。此外,它重量轻,完全适合移动设备(甚至针对 DPI 进行了调整),并且不会以任何显着方式影响内存或 FPS。不到一个月后,Adobe 发布了 Scout。那时我绝对觉得我浪费了几天。
  • 您也可以只使用 Flash Builder 附带的分析器...

标签: performance actionscript-3 removechild addchild


【解决方案1】:

是和不是。孩子们不再位于舞台上,但在调用removeChild() 之前,他们仍然是父母的孩子。这可能是好是坏。显然,它非常适合重用对象,但对于内存管理可能糟糕,因为这些对象只有在其父对象被垃圾回收时才能被垃圾回收。对于一个简单的应用程序,这通常很好。但是对于一些巨大的东西......不是那么多。

对于我现在正在处理的项目(30 页,50,000 行),我创建了一个轻量级的 GUI 框架来处理我的所有 DisplayObjects。除了基本的BitmapShape DisplayObjects 之外的所有东西都扩展了一个扩展Sprite 的类。在那个类中,我有这个功能:

final public function destroy():void {
    this.removeAllEventListeners();

    var i:int, l:int, cur:DisplayObject;
    l = this.numChildren;

    for ( i = 0; i < l; i++ ) {
        cur = this.getChildAt( i );

        if ( cur is XISprite && !this.stopChildXISpriteDestroy ) {
            ( cur as XISprite ).destroy();
        }
        else if ( cur is Sprite ) {
            ( cur as Sprite ).removeChildren();
        }

        if ( cur is Bitmap && ( cur as Bitmap ).bitmapData && !this.stopBitmapDestroy ) {
            ( cur as Bitmap ).bitmapData.dispose();
        }

        if ( cur is Loader && !this.stopLoaderDestroy ) {
            ( cur as Loader ).unload();
        }

        if ( cur is Shape ) {
            ( cur as Shape ).graphics.clear();
        }
    }

    cur = null;
    i = l = NaN;

    this.removeChildren();
}

它基本上对所有对象进行了硬擦除,并允许我轻松地为该类的所有子对象进行垃圾收集。我还在跟踪所有事件侦听器,因此流氓侦听器根本不可能阻止 GC(通过调用 removeAllEventListeners())。我在类中还有一些受保护的标志,允许您停止对某个对象类型的破坏(因此我可以在需要时将 SWF 或图像加载到内存中)

这可能有点矫枉过正,但内存消耗一直是这个应用程序中的一个问题,而该功能确实有助于管理它。这可能超出了您的需要,因此您可以使用默认参数调用 removeChildren(),它将从父对象中删除所有子对象。

作为事后的想法:让您的 DisplayObjectContainers 尽可能简单。尽可能避免嵌套它们。第一个条件,我在每个作为 XISprite 的孩子的 XISprite 上调用 destroy 是 great 但如果有负载和负载的 XISprite 孩子可能是灾难性的,因为 destroy() 调用会堆积互相关注并冻结应用程序。

【讨论】:

  • 真的很喜欢这个答案,我只是在做 bitmapData.dispose() 调用。 graphics.clear() 真的有帮助吗?仅供参考,虽然现在这应该不是问题,但 Loader.unload() 的文档说:在 AIR 3.6 之前,此方法对 iOS 没有影响。
  • @shaunhusain 不知道它对 iOS 3.6 之前的版本没有影响。过去几周我只使用 3.6,所以我想我现在已经注意到了。 graphics.clear() 转储所有矢量数据。所以向量本身被完全破坏并从内存中删除。对实际对象的垃圾收集没有帮助,但与矢量数据相比,该对象是微不足道的。
  • 我认为这里没有足够强调的关键点是您需要删除所有侦听器到您要删除的对象及其子对象。该对象可能无法做到这一点,因为它可能不知道从其他地方添加的侦听器。
  • @AmyBlankenship 我实际上保留了添加到对象的每个事件侦听器的向量(只需覆盖addEventListener),removeAllEventListeneners() 循环遍历并删除每个事件,因此我的自定义 Sprite 类不会不必担心流氓侦听器,但您是对的,这通常是导致对象不被垃圾收集的原因。
  • 只有在您不公开子项(以便可以在父项控制之外添加侦听器)或者您是项目中唯一的编码员时才有效。
猜你喜欢
  • 1970-01-01
  • 2013-10-11
  • 2015-08-04
  • 1970-01-01
  • 2013-12-27
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
相关资源
最近更新 更多