操作脚本:为什么此事件侦听器会导致大量内存消耗



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

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对象的每个引用,也可能不会被垃圾回收。

抓住。重要的是要理解,大多数XML操作都会导致XMLXMLList对象,例如

// 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;

因此,如果不显式将属性强制转换为字符串,而是将 2 个XMLList对象作为函数参数传递(或者看起来如此)。

最后。只需查看Proxy.go(...)就知道它创建了一个委托(这是一种闭包),一个带有存储参数列表的未命名未绑定函数。它应该看起来像这样:

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

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

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

相关内容

最新更新