0
votes

I have an arbitrary number of files that I need to load in an AIR app.

I want to iterate through an array of File object and create and launch Loaders for each one's File.url.

When they are done (event COMPLETED or IOErrorEvent.IO_ERROR), I want to stuff their data somewhere. If they fail, I want to make an exception report. I cannot find any way to reference the File object from the event listener (certainly not the IO_ERROR)

The best way would be to create individual event handlers for each Launcher that had the File information "hard-coded" into it. At the very least, I could use the function itself as an index to a Dictionary:

foo(fileToLoad : File) : void
{
    var theCompletedHandler : Function = 
    {
        var theFile : File = completedHandlerLookup[?????? this function ?????];
        var theData : ImageData = 
            new ImageData(theFile.url, (_loader.content as Bitmap).bitmapData);

        // do something with the data

        delete completedHandlerLookup[?????? this function ?????];
        delete errorHandlerLookup.findByValue(theFile); // [sic]
    }

    var theErrorHandler : Function = 
    {
        var theFile : File = errorHandlerLookup[?????? this function ?????];

        // report the error

        delete errorHandlerLookup[?????? this function ?????];
        delete completedHandlerLookup.findByValue(theFile); // [sic]
    }

    completedHandlerLookup[theCompletedHandler] = theCompletedHandler;
    errorHandlerLookup[theCompletedHandler] = theErrorHandler;

    var theLoader : Loader = new Loader();
    theLoader.addEventListener(Event.COMPLETE, theCompletedHandler); 
    theLoader.addEventListener(IOErrorEvent.IO_ERROR, theErrorHandler); 
    theLoader.load(new URLRequest(fileToLoad.url));

Can I use event.currentTaget and use the Loader instance as an index? Will that have any weird dependencies ?

Cheers

1

1 Answers

2
votes

You can use event.currentTarget as a index look-up, as long as you clear all your references you should have no issues. Note however, loader event listeners are added to loader.contentLoaderInfo, so loader would be accessed through e.currentTarget.loader.

Also worth mentioning, is that a simpler approach to this situation would to build an queue based system, so it only loaded one file at a time. For example storing all files in an array. Then on COMPLETE or IO_ERROR you would handle the current file and then start the next. This would be quite a bit better resource wise (only one loader), and avoid garbage collection issues.

I'm also a little curious why you are anonymous functions? They are not very good from a garbage collection stand point, and actually complicate this situation. Is that a requirement?

Edit: Here's a rough, (and incomplete) example of how a queue based system would solve this issue.

var loader:Loader;
var queue:Array;

function addFile(file:File):void
{
     queue.push(file);
}

function handleLoadedAsset(e:Event):void 
{
    var currentFile:File= queue[0];
    //do whatever
    stepQueueForward();
}

function handleFailedAssetLoad(e:IOErrorEvent):void 
{
    var currentFile:File = queue[0];
    //clean up
    stepQueueForward();
}

function stepQueueForward():void
{
    queue.splice(0, 1);
    var nextFile:File = queue[0];
    loader.load(new URLRequest(nextFile.url));
}