AS3内存保护(Loaders / BitmapDatas / Bitmaps / Sprites)

时间:2009-11-05 01:40:03

标签: flex flash actionscript-3 flex3

我正致力于降低AS3应用的内存需求。我知道,一旦没有对象的剩余引用,它就会被标记为垃圾收集的候选者。

尝试删除对不再使用的Loaders的引用是否值得?我的第一个想法是它不值得。

原因如下: 我的精灵需要永久引用它们显示的位图(因为精灵总是在我的应用程序中可见)。因此,位图不能被垃圾收集。 Bitmaps依赖于BitmapData对象来获取数据,因此我们无法摆脱它们。 (到目前为止,这一切都非常简单。)

这是我不确定发生了什么的地方: BitmapData是否具有对Loader加载的数据的引用?换句话说,BitmapData本质上只是一个包含引用到loader.content的包装器,还是数据从loader.content复制到BitmapData?

如果保留了引用,那么我不会通过垃圾收集我的装载器得到任何东西......

思想?

3 个答案:

答案 0 :(得分:1)

在第三方产品中使用AMF让我相信Loader类试图实例化给定内容类型的新类(在这种情况下,它将是一个Bitmap类实例)。您可能正在从Bitmap实例构造一个新的BitmapData对象。从那里我假设Loader实例引用了Bitmap实例,在您的情况下,您的代码也引用了Bitmap实例。除非在某些时候你正在调用BitmapData.clone()。

还有几种方法可以强制GC。 Force Garbage Collection in AS3?

您可能会发现将一些任意大的对象附加到某个东西上很有用,然后强制GC查看该东西是否被清理或浮动。如果您使用Windows,procmon(http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx)之类的东西比任务管理器更有助于进行此类外部检查。

这当然有点试验和错误,但由于缺乏像Visual VM(https://visualvm.dev.java.net/)这样的东西,我们在Flash世界中有点不知所措。

答案 1 :(得分:1)

这是一个很好的问题,但据我所知,答案是否定的 - Bitmap和BitmapData对象都没有对加载它们的加载器的引用,所以你可以安全地使用它们而不用担心它们会阻止你的加载器被收集。

但是,如果您想完全确定,请使用clone() method of the BitmapData class

  

<强>克隆()

     

返回一个新的BitmapData对象   是原始实例的克隆   与所包含的精确副本   位图。

例如:

private function onCreationComplete():void
{
 var urlRequest:URLRequest = new URLRequest("MyPhoto.jpg");
 var loader:Loader = new Loader();
 loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete, false, 0, true);
 loader.load(urlRequest);
}

private function loader_complete(event:Event):void
{
 var img1:Image = new Image();
 img1.source = Bitmap(event.target.content);
 addChild(img1);

 var img2:Image = new Image();
 img2.source = new Bitmap(event.target.content.bitmapData.clone());
 addChild(img2);
}

这里,img1的源代码是从加载器返回的BitmapData对象显式转换的Bitmap。 (如果你检查FlexBuilder中的引用,你会发现它们是相同的。)但是img2的源代码是一个克隆 - 新的字节串,新对象,新引用。

希望有助于解释事情。但是,负责保持对象不被垃圾收集的罪魁祸首通常是事件处理程序。这就是为什么我在设置我的听众时设置useWeakReference flag(见上文),几乎完全是这样,除非我有充分的理由不这样做:

  

useWeakReference :布尔值(默认=   false) - 确定是否   对听众的引用很强或   弱。强引用(默认)   阻止你的听众   垃圾回收。弱参考   没有。

答案 2 :(得分:0)

您可以在完整的侦听器中设置一个存储位图的变量,然后再销毁该对象

public function COMPLETEListener(e:Event){
myBitmap = e.target.loader.content;
}

public function destroy(){
if(myBitmap is Bitmap){
                        myBitmap.bitmapData.dispose(); 
    }
}

适合我加载一些大图像并查看任务管理器的区别