AS3 - Свободная память (Loader, BitmapData)? - PullRequest
1 голос
/ 05 января 2012

По какой-то причине мое приложение использует все больше и больше памяти во время работы, и я не могу понять, как выгружать старые данные, которые мне больше не нужны.

Я использую 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 ]

3 голосов
/ 05 января 2012

Как только вы закончите с myBitmapData, позвоните myBitmapData.dispose() и myBitmapData = null. Помните, что после вызова dispose() ваш объект BitmapData больше не может использоваться, поэтому вам нужно создать новый экземпляр (myBitmapData = new BitmapData()).

Кстати, я мало анализировал ваш код, но заметил, что вы скопировали bitmapData каждого изображения с помощью draw(), а затем поработали над ним. Вы можете напрямую работать с содержимым загруженных изображений, что также сэкономит память:

myBitmapData = Bitmap(event.target.content).bitmapData;

и не забудьте null каждое изображение перед переходом к следующему кадру, если вы не собираетесь использовать их позже.

1 голос
/ 06 января 2012

К сожалению, существует ошибка, препятствующая когда-либо освобождать загрузчик памяти, см. Здесь: https://bugbase.adobe.com/index.cfm?event=bug&id=3071138. Согласно моим тестам, это может быть связано с тем, как быстро вы хотите удалить ранее загруженный контент, но это догадка , не принимайте это как должное.

Другие вещи: вызов BitmapData.dispose() освобождает память «немедленно», но если вы этого не сделаете, то экземпляры BitmapData по-прежнему остаются в GC, однако это может занять больше времени, и растягивающиеся растровые изображения могут создавать впечатление памяти течь.

System.gc() доступен только в отладчике, что означает, что ваши конечные пользователи не смогут его использовать.

Задавать переменным, особенно локальным переменным, значение null после того, как объект больше не используется, не имеет смысла, если бы компилятор был лишь немного умнее, он, вероятно, идентифицировал бы его как мертвый код и вообще удалил бы. Установка элементов данных в null полезна, только если вы на самом деле хотите, чтобы они были нулевыми по любой причине, то есть, как они это называют, «причине бизнес-логики», не пытайтесь «помочь» GC, все шансы у вас будут приносить больше вреда, чем пользы. Когда я сталкиваюсь с кодом, который присваивает null, он обычно загорается красной лампочкой, это скорее плохой дизайн или избыточность. Если ваш код хорош, вам не нужно это делать.

0 голосов
/ 05 января 2012

В других ответах рассказывалось, как обращаться с BitmapData, но я заметил, что Loader, похоже, тоже держатся за память.К сожалению, я не могу указать на какие-либо конкретные источники, кроме моего опыта.Вы можете попробовать посмотреть, что вытряхивает:

Переместите строку

myLoader = new Loader();

из функции loadImage() и создайте экземпляр этой переменной в конструкторе класса.Это позволит вам снова и снова использовать один и тот же экземпляр Loader.

0 голосов
/ 05 января 2012

Вы находитесь в рекурсии, поэтому да, вы не выпускаете загруженное изображение для предварительного просмотра.

Попробуйте установить myBitmapData = null перед вызовом loadImage() еще раз.

Если ничего не происходит, вы можете попробовать принудительно запустить сборщик мусора, вызвав System.gc() перед loadImage:

myBitmapData = null;
System.gc();
loadImage();

Но это не очень хорошая практика, говорят они. : P

Если ничего не работает, просто уберите рекурсию, которая может помочь.

...