How to free up memory after using a Filererence?

Asked

Viewed 304 times

2

FileReference.load does not have a function to download, just as there is new Loader().unload.

Must be a Flash BUG or Filereference needs to be improved, like in a new version add a function like this: FileReference.unload();

Or I’m wrong and there’s a solution?

I tried to set NULL for a variable of the type :FileReference, but clearly this does not work because the Flash works with GC (Garbage Collector), but this is not the focus of the issue.

The problem is that when loading multiple files with FileReferenceList it takes a lot of memory, but I can’t release memory after the process.

How to free up memory after using a FileRerence?

My code:

Main as.

package {
     import com.mainpackage.LoaderTestCase;

     import flash.net.FileReferenceList;
     import flash.net.FileReference;
     import flash.net.FileFilter;
     import flash.events.Event;
     import flash.display.MovieClip;

     public class Main extends MovieClip {
          private var listFiles:Array;
          private var allTypes:Array;
          private var fileRef:FileReferenceList;
          private var test:int;

          public function Main()
          {
               test = 0;
               listFiles     = [];
               allTypes     = [];
               fileRef          = new FileReferenceList();
               fileRef.addEventListener(Event.SELECT, select);

               fileRef.browse(allTypes);
          }

          private function select(e:Event):void
          {
               listFiles = fileRef.fileList;

               for(var i:uint=0, j:uint=listFiles.length; i<j; i++)
               {
                    insert(i);
               }
          }

          private function insert(c:int):void
          {
               var fire:LoaderTestCase = new LoaderTestCase(listFiles[c]);

               fire.destroy(function():void
               {
                    //Delete LoaderTestCase after timeout ???
                    fire = null;
                    test++;
                    if(test>=listFiles.length) {//Remove FileReference
                         fileRef.removeEventListener(Event.SELECT, select);
                         fileRef = null;

                         for(var i:uint=0, j:uint=listFiles.length; i<j; i++) {
                              listFiles[i] = null;
                         }
                         listFiles = null;

                         trace("Clear memory");
                    }
               });
          }
     }
}

Loadertestcase.as

package com.mainpackage
{
    import flash.net.FileReference;
    import flash.events.Event;
    import flash.display.Loader;

    public class LoaderTestCase
    {
        private var file:FileReference;
        private var loader:Loader;
        private var callback:Function;

        public function LoaderTestCase(e:FileReference)
        {
            file = e;
            trace("OPEN: " + file.name);
            file.addEventListener(Event.COMPLETE, loadFile);
            file.load();
            e = null;
        }

        public function loadFile(e:Event):void
        {
            file.removeEventListener(Event.COMPLETE, loadFile);

            trace("LOAD: " + file.name);

            file    = null;
            e       = null;
            callback();
        }

        public function destroy(a:Function):void
        {
            callback = a;
        }
    }
}

2 answers

3


I managed to reach my goal, discovered something with FileReferenceList.fileList

If I do this FileReferenceList.fileList[5] = null; (when the "sixth file" is no longer being used) Flash immediately releases the memory of this FileReference specific.

What I mean by this is that if you do this the Flash does not release memory:

private var file:FileReference;
...
file = FileReferenceList.fileList[5];
...
file = null;

But this releases memory "immediately":

FileReferenceList.fileList[5] = null;

Worked at all, in Adobe Flash Professional, Plugins installed on the machine and Pepperflash (Chrome Plugin).

Code in operation:

package {
    import flash.net.FileReferenceList;
    import flash.net.FileReference;
    import flash.net.FileFilter;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.display.Sprite;

    public class Main extends Sprite
    {
        private var listFiles:Array;
        private var allTypes:Array;
        private var fileRef:FileReferenceList;
        private var tmpFile:FileReference;
        private var i:uint=0;
        private var j:uint=0;
        private var timer:uint;
        private var imageTypes:FileFilter;
        private var enable:Boolean;

        public function Main()
        {
            imageTypes   = new FileFilter(
                "Images (*.JPG;*.JPEG;*.JPE;)", "*.jpg; *.jpeg; *.jpe;"
            );
            listFiles   = [];
            allTypes    = [imageTypes];

            eventBrowse(true);
        }

        private function eventBrowse(a:Boolean):void
        {
            enable = a;
            if (a === true) {
                stage.addEventListener(MouseEvent.CLICK, browse);

                fileRef = new FileReferenceList();
                fileRef.addEventListener(Event.SELECT, select);
            } else {
                fileRef.removeEventListener(Event.SELECT, select);
                fileRef = null;

                stage.removeEventListener(MouseEvent.CLICK, browse);
            }
        }

        private function browse(e:MouseEvent):void
        {
            if (enable === true) {
                fileRef.browse(allTypes);
            }
        }

        private function select(e:Event):void
        {
            listFiles = fileRef.fileList;

            eventBrowse(false);

            i = 0;
            j = listFiles.length;

            if (j > 0) {
                loadNextFile();
            }
        }

        private function loadNextFile():void
        {
            if (false === (i < j)) {
                listFiles = null;
                trace("Free memory???");
                trace("--------------");
                trace("listFiles:"+ listFiles);
                trace("allTypes:" + allTypes);
                trace("fileRef:" + fileRef);
                trace("tmpFile:" + tmpFile);
                trace("i:" + i);
                trace("j:" + j);
                trace("timer:" + timer);
                trace("--------------");
                eventBrowse(true);
                return;
            }

            tmpFile = listFiles[i];
            trace("Initiate load:" + tmpFile.name);
            tmpFile.addEventListener(Event.COMPLETE, loadedFile);
            tmpFile.load();
        }

        private function loadedFile(f:Event):void
        {
            trace(listFiles);
            trace("Finished load:" + tmpFile.name);
            tmpFile.removeEventListener(Event.COMPLETE, loadedFile);

            tmpFile = null;
            listFiles[i] = null;

            ++i;
            loadNextFile();
        }
    }
}
  • 1

    Very good @Guilhermenascimento!

2

This is not a bug. In fact the Garbage Collector (Garbage Collector) Flash Player runs in unpredictable ways. He is responsible for keeping the ram memory of the machine free and we have to take that into consideration yes.

Unfortunately there is no way to release machine memory instantly (with the exception of class BitmapData which has a method called .Disposis()), as soon as the Garbage Collector only runs when it really needs to free the memory and also, there is no control of this object on the part of the Programmer but by the Flash Player’s own VM.

Adobe’s own reference suggests/determines that GC "destroy" the unused objects you set the instances for them as null, that most of the time the active.

What may be happening with your code is that the GC is not yet able to capture objects that are not instantiated, because the object itself was loaded in asynchronous through a Event, which makes the definition impossible null, since the only way to access it is by a method "only seitura" e.currentTarget().

It is not only a particularity of Flash, as said, there are other languages that use this same scheme. However the Flash is still far behind to achieve this perfection.

I don’t know what the ultimate goal of your application is after loading the files, but you could try loading them into the same object ByteArray, dividing each file by parts, recording and then generating the final file of each and after, define this object as null.

Another way is you build a "Gambiarra", sending your current frame to a totally empty and without functions (Like another Scene, for example), this usually activates the GC.

  • I recreated the code in an Async way, with only one class. Obitive the following results: 1) "Firefox/Safari (Flash plugin 12.0.0.77): Starts with 9Mb, reaches 135Mb and ends with 17Mb." 2) "Google Chrome (Pepperflash 12.0.0.70): Starts with 12Mb, reaches 132Mb and ends with 17Mb." 3) "Flash CS5 (Flash Player 10/12 without running CS5): Starts with 6Mb, reaches 185Mb and ends with 185Mb."

  • That was one hell of a difference! Actually running the Flash Player directly on the Desktop there will be no change, I believe that on the web GC still runs more perfectly.

  • Strangely Flash CS5 (IDE) uses the application itself ./Adobe Flash CS5/Release/FlashPlayer.exe to do the job and did a test using the Monsterdebugger and it shows that releases almost every memory, the problem really only occurs when the Flashplayer runs without the IDE.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.