AS3 - 可用内存(Loader,BitmapData)?

时间:2012-01-05 12:51:44

标签: flash actionscript-3 flex air

出于某种原因,我的应用程序在运行时使用的内存越来越多,我无法弄清楚如何转储我不再需要的旧数据。

我使用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;
            }

        }

4 个答案:

答案 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实例。