出于某种原因,我的应用程序在运行时使用的内存越来越多,我无法弄清楚如何转储我不再需要的旧数据。
我使用Loader加载.png 然后我使用BitmapData来存储图像,这样我就可以检查每个像素并存储结果。
然后我循环x次。
当我开始第二次运行时,我不再需要旧信息,但看起来我的应用程序仍在存储数据(加载的图像)..
以下是我的一些代码:
public function loadImage():void{
myLoader = new Loader();
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
if (currentFrame.toString(10).length == 1){
currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 1) + currentFrame + txtImageType.text;
}
if (currentFrame.toString(10).length == 2){
currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 2) + currentFrame + txtImageType.text;
}
if (currentFrame.toString(10).length == 3){
currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 3) + currentFrame + txtImageType.text;
}
trace(currentFrameURL + " sent to loader...");
myLoader.load(new URLRequest(currentFrameURL));
}
public function imageLoaded(event:Event):void{
myLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, imageLoaded);
myBitmapData = new BitmapData(parseInt(txtWidth.text),parseInt(txtHeight.text),false);
myBitmapData.draw(event.currentTarget.content);
//Generate preview of current image being processed..
//myPreviewImage.source = myBitmapData;
labelProgress.text = "Current process: " + (currentFrame + 1) + "/" + (parseInt(txtFrames.text));
for(var y:int=0; y < parseInt(txtHeight.text) ; y++){
for(var x:int=0; x < parseInt(txtWidth.text) ; x++){
currentPixelColor = myBitmapData.getPixel(x,y);
myTabelClass.recordPixel(currentPixelColor);
}
}//ett bilde ferdig scannet og lagret
currentFrame++;
if(currentFrame < parseInt(txtFrames.text)){
myTabelClass.newImg(currentFrame);
trace("sending newImg command: " + currentFrame);
loadImage();
}else{
//All frames done..
//myTabelClass.traceResult();
Alert.show("All images scanned!\n\nClick 'OK' to add new data to XML.", "Images scanned", Alert.OK, this, insertDataToXML);
btnSave.enabled = true;
btnTest1.enabled = true;
}
}
答案 0 :(得分:3)
完成myBitmapData
后,请致电myBitmapData.dispose()
和myBitmapData = null
。请注意,在致电dispose()
后,您的BitmapData
对象不再可用,因此您必须创建一个新实例(myBitmapData = new BitmapData()
)。
顺便说一句,我没有对你的代码进行过多的分析,但我注意到你用draw()
复制了每个图像的bitmapData,然后对它进行了处理。您可以直接使用加载的图像内容,这也可以节省内存:
myBitmapData = Bitmap(event.target.content).bitmapData;
并且如果您以后不打算使用它们,请不要忘记null
每个图像,然后再继续使用它们。
答案 1 :(得分:1)
不幸的是,有一个错误阻止Loader释放内存,请参阅此处:https://bugbase.adobe.com/index.cfm?event=bug&id=3071138。根据我的测试,它可能与你想要多快处理以前加载的内容有关,但这是一个 guess ,不要把它视为理所当然。
其他事情:调用BitmapData.dispose()
“立即”释放内存,但如果不这样做,那么BitmapData实例仍然是GC,但是,这可能需要更长时间,而游荡位图可能会产生一种印象内存泄漏。
System.gc()
仅在调试程序中可用,这意味着您的最终用户将无法使用它。
在不再使用对象之后将变量(尤其是局部变量)设置为null是没有意义的,如果编译器只是更聪明一点,它可能会将其识别为死代码并完全删除。将数据成员设置为null仅在您实际希望它们因任何原因而为空时才有用,这就像他们所说的那样,“业务逻辑原因”,不要试图“帮助”GC,所有机会都是做更多的伤害然后好。当我遇到分配null
的代码时,这通常会点亮一个红色灯泡,这是一个糟糕的设计或冗余。如果你的代码是好的,你就不需要这样做。
答案 2 :(得分:0)
你正在递归,所以是的,你没有发布加载的预览图像。
尝试再次拨打myBitmapData = null
之前设置loadImage()
。
如果没有任何反应,您可以尝试在loadImage:
之前调用System.gc()
强制垃圾收集器
myBitmapData = null;
System.gc();
loadImage();
但这并不是他们所说的好习惯。 :P
如果没有任何作用,只需删除可能有用的递归内容。
答案 3 :(得分:0)
其他答案已经涵盖了如何处理BitmapData
,但我注意到Loader
似乎也坚持了记忆。不幸的是,除了我的经验,我无法指出任何具体的来源。你可以尝试一下,看看有什么动摇:
移动线
myLoader = new Loader();
out loadImage()
函数并在类构造函数中实例化该变量。这样您就可以一遍又一遍地重复使用相同的Loader
实例。