在这种情况下如何避免内存泄漏?

时间:2013-10-07 18:06:51

标签: actionscript-3 flash garbage-collection

为了防止ActionScript 3.0中的内存泄漏,我在必须使用向量的类中使用成员向量,例如:

public class A
{
    private var mHelperPointVector:Vector.<Point> = new Vector.<Point>();


    public static GetFirstData():Vector.<Point>
    {
        mHelperPointVector.length = 0;
        ....
        return mHelperPointVector;
    }


    public static GetSecondData():Vector.<Point>
    {
        mHelperPointVector.length = 0;
        ....
        return mHelperPointVector;
    }
}

然后我让消费者​​使用GetFirstData和GetSecondData方法,存储对这些方法返回的向量的引用,例如:

public function OnEnterFrame():void
{
    var vector:Vector.<Point> = A.GetSecondData();
    ....
}

这个技巧似乎很好,但有时我需要在一段时间后处理由GetSecondData()返回的向量,在这种情况下,此向量会被另一个对GetSecondData()或GetFirstData()的调用覆盖。 ..解决方案是将矢量复制到一个新的矢量......但在这种情况下最好避免这种技巧。你是如何处理这些问题的?我必须使用大量的向量(每个长度在1-10之间)。

1 个答案:

答案 0 :(得分:1)

关于垃圾收集的事情只是尽量避免实例化(和处理)。很难说什么是最好的方法,因为我看不出你使用你的矢量数据是怎么/为什么,但乍一看我认为用你的方法你将不断丢失数据(你几乎创建等效的弱实例,因为它们可以很容易地被覆盖)并且改变Vector的长度并不能真正避免垃圾收集(它可能会延迟并减少它,但你仍然会不断地丢弃数据)。

我坦率地认为你没有使用点向量的内存泄漏,除非你左右泄漏对向量的引用。在这种情况下,最好修复这些剩余的引用,而不是简单地提出重用相同向量的解决方案(可能会产生更多的不利影响)。

然而,如果你真的关注内存,我认为你最好的解决方案就是提前创建你需要的所有向量(如果它是一个固定的数字,你知道它们的长度超前于时间)或者更好的是,使用Object Pools。后者肯定是一个更强大的解决方案,但它需要一些设置,通过创建一个Pool类,然后使用它。要把它放在代码中,一旦实现,就会像这样使用:

// Need a vector with length of 9
var myVector:Vector.<Point> = VectorPool.get(9);

// Use the vector for stuff
...

// Vector not needed anymore, put it back in the pool
VectorPool.put(myVector);
myVector = null; // just so it's clear we can't use it anymore

VectorPool将控制您拥有的Vector列表,让代码的其他部分根据需要“借用”向量(在VectorPool中将它们标记为“已使用”)并将其返回(将它们标记为未使用的)。如果未使用的对象列表中没有可用的向量,您的代码也可以根据需要在现场(get()内)创建向量;这会使它更灵活(在某些情况下不推荐,因为你仍然花时间进行实例化,但在这种情况下可能忽略不计)。

这是一个非常宏的解释(你仍然需要编写VectorPool),但是像这样的对象池被认为是避免重新实例化以及对象的垃圾收集的最终解决方案。只是要重复使用。

供参考,这是我用作非常通用的对象池的内容: https://github.com/zeh/as3/blob/master/com/zehfernando/data/ObjectPool.as

或者更专业的一种,我在需要一堆相似大小的一次性BitmapData实例的情况下使用它们: https://github.com/zeh/as3/blob/master/com/zehfernando/data/BitmapDataPool.as

我相信在您需要的模具中实现VectorPool类与上面的链接类似。

作为旁注,如果表现是一个问题,我建议也使用固定长度的矢量,例如。

// Create a vector of 9 items, filled with `nulls`
var myPoints:Vector.<Point> = new Vector.<Point>(9, true);

这使得它更快,因为您不会随着时间的推移进行微量分配。您必须直接设置项目,而不是使用push()

myPoints[0] = new Point(0, 0);

但这实际上是一种强制优势,因为设置矢量项比push()快。