Actionscript 3 AS3在BitmapData内存泄漏上绘制精灵
我有一个AIR应用程序,可以从Flash编辑器渲染图像。您可以自定义多个曲面-它们都具有相同的宽度和高度。然后,每个曲面都由AIR应用程序渲染 我正在努力解决一个无法解决的内存泄漏问题 对于我需要渲染的每个曲面,我都有一个包含许多组件的精灵(其他精灵-一些具有事件侦听器、位图数据和其他子组件、精灵等) 我已经知道要进行垃圾收集的BitmapData问题,我测试了这两个问题:Actionscript 3 AS3在BitmapData内存泄漏上绘制精灵,actionscript-3,flash,memory-leaks,air,Actionscript 3,Flash,Memory Leaks,Air,我有一个AIR应用程序,可以从Flash编辑器渲染图像。您可以自定义多个曲面-它们都具有相同的宽度和高度。然后,每个曲面都由AIR应用程序渲染 我正在努力解决一个无法解决的内存泄漏问题 对于我需要渲染的每个曲面,我都有一个包含许多组件的精灵(其他精灵-一些具有事件侦听器、位图数据和其他子组件、精灵等) 我已经知道要进行垃圾收集的BitmapData问题,我测试了这两个问题: 为每个渲染创建一个新的位图数据,然后dispose()并指向null 为每次渲染重用单个位图数据 内存泄漏仍然以同样的
- 为每个渲染创建一个新的位图数据,然后dispose()并指向null
- 为每次渲染重用单个位图数据
var bm:BitmapData = new BitmapData(destDim.x, destDim.y, true, bgColor);
var mtx:Matrix = new Matrix();
trace('before drawing :'+(System.privateMemory/1024));
bm.draw(myBigSprite, mtx, null, null, null, true);
trace('after drawing :'+(System.privateMemory/1024));
var result:Bitmap = new Bitmap(bm, PixelSnapping.NEVER, true);
//return result and encode Bitmap to png
result.bitmapData.dispose();
result.bitmapData = null;
result = null;
结果:
before drawing :208364
after drawing :302816
Wrote bitmap to file: surface0.png
before drawing :303296
after drawing :446160
Wrote bitmap to file: surface1.png
before drawing :446160
after drawing :565212
Wrote bitmap to file: surface2.png
before drawing :565924
after drawing :703100
Wrote bitmap to file: surface3.png
before drawing :703572
after drawing :834420
Wrote bitmap to file: surface4.png
我觉得我在draw函数行为中遗漏了一些东西。看起来我已经创建了myBigSprite组件的新实例,这些实例在draw操作之后仍然存在
我试图在每个循环结束时完全销毁MyBigspite,它不会改变任何东西
任何暗示都将不胜感激 您应该在任何函数之外声明您的
Bitmap
和BitmapData
,然后简单地在循环内部循环使用它们(而不是创建一个新的
要添加到内存中的任何内容)
当您确定不再需要来自bm
变量的位图数据时,仅在最后一幅图像上使用.dispose()
。否则,如果已释放,则必须再次创建一个新的备选方案var someThing:BitmapData=new BitmapData
,以供进一步使用
////# declare globally (not inside some specific function..)
//var destDim :Point = new Point(your_X_num , your_Y_num);
//var bgColor :uint = 0x505050;
var bm:BitmapData = new BitmapData(destDim.x, destDim.y, true, bgColor);
var result:Bitmap = new Bitmap(bm, PixelSnapping.NEVER, true);
//result.bitmapData = bm; //can be set here but done within function for clarity...
var mtx:Matrix = new Matrix();
////# update bitmap by replacing its bitmapdata with new colour values of existing pixels
function Here_is_my_loop (): void
{
trace('before drawing :'+(System.privateMemory/1024));
//overwrite pixel colours in bitmap (result)
bm.draw(myBigSprite, mtx, null, null, null, true);
result.bitmapData = bm; //update bitmap
trace('after drawing :'+(System.privateMemory/1024));
//return result and encode Bitmap to png
//result.bitmapData.dispose();
//result.bitmapData = null;
//result = null;
}
好了,伙计们,我终于明白并解决了这个问题 首先,我安装并运行了Adobe Scout。很好的工具 正如您可能看不到的(加上法语),我生成了3个与边对应的曲面。右侧的“大”绿色条消耗大量内存,表示“位图显示对象”。有趣!以前从没听说过 在谷歌搜索之后,我发现了这篇文章: 它解释了 例如,在前面显示的代码摘录中,加载 pict加载程序对象的操作完成后,pict对象将 加载一个子显示对象,即位图。访问 此位图显示对象,可以写入pict.getChildAt(0) 所以我开始不明白,不知何故,可能位图对象作为子对象附加在
myBigSprite
的某些对象上
最后,我创建了一个递归函数来搜索并销毁draw
操作后myBigSprite
中包含的所有Bitmap
、BitmapData
和ByteArray
对象
//inside render function
bm.draw(myBigSprite, mtx, null, null, null, true);
destroyDisplayObjects(myBigSprite);
private函数销毁显示对象(obj):无效{
if(obj中的“numChildren”){
对于(var i:int=0;i您如何知道垃圾收集进程运行了?您是否强制它?也正如旁注一样,通过调用System.gc()强制gc)据我所知,只在debug player中工作。正如您所见,绘图操作结束和下一个操作开始之间的内存几乎相等,但其间有许多内存消耗操作。特别是将位图编码为png。因此我假设GC进程正在完成其工作,因为我想要清理的所有资源都已被清除eaned除了draw函数外。我从未显式调用System.gc()。是否设置“结果”设置为null,因为它包含对bitmapdata的引用?是的,我编辑了我的代码段,因为它不清楚,对不起。@Bedu33通常情况下,垃圾收集器是惰性的,不会在任何未使用的内存未使用时立即处理。因此我建议您尝试调用System.gc()明确并查看内存测量值。如果这样做可以解决您的问题,那么这不是内存泄漏,而是GC懒惰。感谢您的回答。不幸的是,正如我在原始帖子中所说,我对重用的BitmapData得到了完全相同的结果。不过,我用您的解决方案再试了一次,并且我确认它具有相同的结果sult.Hmm,我不确定上次我是如何错过了“为每次渲染重复使用单个位图数据”的,但是,在循环中使用new
是消耗内存的好方法。我的代码应该只是覆盖现有数据,所以无法理解如何以某种方式添加更多的新数据(增加内存使用量)。我将在可能的情况下研究如何使用闪存。“我的代码应该只是覆盖已经存在的数据,所以我无法理解如何以某种方式添加更多的新数据(增加内存使用量)”这也是我的问题:)
private function destroyDisplayObjects(obj):void{
if ("numChildren" in obj){
for (var i:int = 0; i<obj.numChildren; i++)
{
destroyDisplayObjects(obj.getChildAt(i));
}
}
else {
if (flash.utils.getQualifiedClassName(obj) == "flash.display::Bitmap"){
//trace ('FREE BITMAP');
obj.bitmapData.dispose();
obj.bitmapData = null;
obj = null;
return;
}
else if (flash.utils.getQualifiedClassName(obj) == "flash.display::BitmapData"){
//trace ('FREE BITMAPDATA');
obj.dispose();
obj = null;
return;
}
else if (flash.utils.getQualifiedClassName(obj) == "flash.display::ByteArray"){
//trace ('FREE BYTEARRAY');
obj.clear();
obj = null;
return;
}
return;
}
}