1 Reply Latest reply on Nov 4, 2009 8:28 PM by Bertrand G.

    Load / unload numerous images in air application (memory leak?)

    Bertrand G. Level 1

      Hi,

       

      after struggling for a few days with this, I realized I need help!

       

      I am trying to make an application load and display A LOT (hundreds) of images thumbnails at various position in a big area. The problem is that when I try to unload and reload images, I end up with an increasing memory, that does not get collected by the garbage collector.

       

      My first challenge was to load images from anywhere in the computer (I am quite new to flex), which I solved by using a File reference and a Loader using the url extracted from the file:

       

                     private function createImage():void {

                               var img_:String = "1905_a_mondrian.jpg";

                               var imageFile:File = new File();

                               imageFile.nativePath = imagesPath + "/" + img_;

                         

                         

                               var imageLoader:Loader = new Loader();

                               // useWeakReference permits the GC to collect the memory when the eventListener is dropped

                               imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded, false, 0, true);

                               imageLoader.load(new URLRequest(imageFile.url));

                               imageFile = null;

                     }

       

       

      I make sure I remove the eventListener in the loaded method:

       

           e.target.content.removeEventListener(Event.COMPLETE, loaded);

       

       

      And then Populate an external component:

       

      <?xml version="1.0" encoding="utf-8"?>

      <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"

                xmlns:s="library://ns.adobe.com/flex/spark"

                xmlns:mx="library://ns.adobe.com/flex/halo"

                x="-100" y="-100"  width="200" height="200" >

           <!-- The trick is right above this line: offset the anchor point to center the component around -->

          

           <fx:Script>

                <![CDATA[

                     import mx.controls.Image;

                    

                     [Bindable]

                     public var image:Image;

                    

                ]]>

           </fx:Script>

          

           <fx:Declarations>

                <!-- Place non-visual elements (e.g., services, value objects) here -->

           </fx:Declarations>

          

           <mx:Image id="img_" source="{image}" horizontalCenter="0" verticalCenter="0" autoLoad="true" />

          

           <!-- impair width and height results in problems for centering the ellipse (e.g. for rotation) -->

           <s:Ellipse height="4" width="4"  horizontalCenter="0" verticalCenter="0" >

                <s:fill>

                     <s:SolidColor color="0x00FF00"/>

                </s:fill>

           </s:Ellipse>

      </s:Group>

       

      I populate a Dictionary to keep a track of all the component created. Finally I nullify all that I can to hint the garbage collector.

       

      Now I have a function to empty the Dictionary (componentBag below) when we want to unload the images:

       

                     protected function button1_clickHandler(event:MouseEvent):void

      {

                               for each ( var g : Group in componentBag )

                               {  

                                         ((ImgPanel)(g.getChildAt(0))).img_.unloadAndStop(false);

                                         ((ImgPanel)(g.getChildAt(0))).image = null;

                                         delete componentBag[g.uid];

                                         g.removeElementAt(0);

                                         this.removeElement(g);

                                         g = null;

                               }

           triggerGC();

                     }

       

       

      PROBLEM: using profiler, the loading/unloading works once or twice and after the memory keeps increasing... And if I launch the application, wait for a while and do a load/unload, the garbage collection only recovers a few megabytes, far from what was allocated for displaying the images.

       

      What am I missing? Is there a problem with loading a lot of images? Has anyone done this?

       

      In attachment is the full test code, the ImgPanel goes inside a 'views' package

        • 1. Re: Load / unload numerous images in air application (memory leak?)
          Bertrand G. Level 1

          Thanks to Anton_AL, I finally solved this problem by using an URLLoader AND a plain Loader:

           

          var loader: URLLoader = new URLLoader( );

          loader.dataFormat = URLLoaderDataFormat.BINARY;

          loader.addEventListener(Event.COMPLETE, onLoadingComplete );

          loader.load( new URLRequest(file.url) );

           

          private function onLoadingComplete( e: Event ):void

          {

               var loader: Loader = new Loader( );

               loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onParsingComplete );

               loader.loadBytes( e.target.data );

          }

          private function onParsingComplete( e: Event ):void

          {

               var img: BitmapImage = new BitmapImage( );

               img.source = (e.target.content as Bitmap).bitmapData;

               _images.push( img );

          }

           

           

          private function onImageLoaded( e:Event ):void

          {

               var img: Image = e.target as Image;

               img.removeEventListener( Event.COMPLETE, onImageLoaded );

           

               _images.push( img );

          }

           

          See Anton's thread here: http://forums.adobe.com/message/2358653#2358653