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

Actionscript: Why does this Event Listener cause massive memory consumption

我有一组按钮,我附加了这样的事件侦听器。

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 对象,而不仅仅是我需要的元素。

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

试试。 Flash 在处理任何与 XML 相关的东西时非常懒惰。如此懒惰,事实上,它甚至有 System.disposeXML(...) 方法,否则 XML 对象可能不会被垃圾回收即使您有意识地删除了对它的所有引用。

Catch. 重要的是要理解,大多数 XML 操作会导致 XMLXMLList 对象,say

// 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 (which is a type of closure), 一个未命名的未绑定函数,带有存储的参数列表。它看起来应该类似于:

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

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

所以,你有它。一些未命名的函数(几乎永远)在玩家记忆中的某个地方保留了一个未类型化参数列表,其中包含您的 XMLList 对象(它们是持久的并且不容易处理) .然后你以这种方式创造了 150 个这样的怪物。喷泉和 niagaras 内存泄漏是很自然的。