Actionscript:为什么这个事件监听器会导致大量内存消耗

时间:2017-07-16 13:06:59

标签: actionscript-3 actionscript

我有一系列按钮,我附上了这样的事件监听器。

arr[c].addEventListener(MouseEvent.MOUSE_UP, Proxy.go(this, click, Model.categoriesListXml.category_0[i].category_1[j].@category_id, Model.categoriesListXml.category_0[i].category_1[j].@name));

其中150个使用了32MB内存。

当我使用以下内存时,降至2MB。

var categoryId:String = Model.categoriesListXml.category_0[i].category_1[j].@category_id;
var name:String = Model.categoriesListXml.category_0[i].category_1[j].@name;
arr[c].addEventListener(MouseEvent.MOUSE_UP, Proxy.go(this, click, categoryId, name));

我所做的就是在事件监听器中使用之前将xml元素放在自己的变量中。

有谁知道为什么会这样?

我的猜测是整个XML对象都包含在内,而不仅仅是我需要的元素。

1 个答案:

答案 0 :(得分:4)

我认为它的工作原理如下。

试试。在处理任何 XML 相关的内容时,Flash非常懒惰。事实上,它实际上是懒惰的,甚至还有 System.disposeXML(...) 方法,因为否则 XML 对象可能不会被垃圾收集,即使您有意识地删除了对它的每一个引用

Catch。重要的是要了解,大多数 XML 操作会导致 XML XMLList 对象,说

// XML source.
var X:XML = <root a="1" />;

// You might think it returns String, but no, it is just autocast to String.
var a:String = X.@a;

// If you don't specify data type, this returns XMLList object of length 1,
// with an XML member of type "attribute", name "a" (or maybe "@a"), and so on.
var A:* = X.@a;

因此,如果没有明确地将属性转换为 String ,则会将2个 XMLList 对象作为函数参数传递(或者看起来如此)。

最后。只看 Proxy.go(...)告诉我们它创建了一个delegate({{3}的类型带有存储的参数列表的未命名的未绑定函数。它看起来应该类似于:

public function go(target:Object, method:Function, ...rest:Array):Function
{
    return function():void
    {
        method.apply(target, rest);
    }
}

这符合ECMA标准(可能也适用于 JavaScript ),允许闭包访问所有父方法数据:局部变量和方法参数。

所以,你拥有它。一些未命名的函数在播放器的内存中保存(几乎永远)一个无类型参数列表,其中包含 XMLList 对象(持久且不易处理)。然后你用这种方式创造150个这样的怪物。在喷泉和尼亚加拉斯中,内存泄漏是很自然的。