views:

1617

answers:

5

Hello! First question here; hope you can help. I'm completely flummoxed.

I created a flash slideshow which preloads the images. After preloading the images, it proceeds to load an external flash file and then the images. The problem is, very very occasionally, it will fail to actually load the images into view, and I'll just see the preloading animation, but it might still load the external swf. Additionally, it might do the reverse, and load the images and not load the external swf.

I have no been able to reproduce the latter, although the client has noticed it on a few occasions. The former will happen for me, but only very rarely.

Here is the (I think) relevant code:

function onXMLLoadComplete(e:Event):void {
// create new xml with the received data
xmlSlideshow = new XML(e.target.data);
// get total slide count
// misc xml data
info_holder.mcInfo.lbl_tagline.text = xmlSlideshow.misc.@tagline;
info_holder.mcInfo.goToUrl_btn.lbl_view.text = [email protected]();

intSlideCount = xmlSlideshow..img.length();
//trace(intSlideCount);
imageArray = new Array(intSlideCount);

for (var i:int = 0; i < intSlideCount; i++) {
 //imageArray[i] = new URLRequest(xmlSlideshow..img[i].@src); 
 var loader:Loader = new Loader();
 loader.load(new URLRequest(xmlSlideshow..img[i].@src));
 //trace(xmlSlideshow..img[i].@src);
 loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete); 
 //loader.load(imageArray[i]);
  }
}

function onImageLoadComplete(e:Event):void {

if (++numberOfImagesLoaded == intSlideCount) {
 // animate the info bar and then
 //trace(intSlideCount);
 //trace(numberOfImagesLoaded);
 info_holder.play();
 // switch the first slide without a delay 
 // reset index of images
 //load map div via jQuery
 if (ExternalInterface.available) {
  ExternalInterface.call('openMap');
 }
 intCurrentSlide = -1;
 switchSlide(null);
  }
}

The live site is here: http://www.luxuryportfolio.com - see if any of you can reproduce the above issues...

Thanks!!

A: 

Hi!

I had no problem viewing your (pretty) gallery. Have you tried adding an error handler to your loader?

loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
function onError(e:IOErrorEvent) {
    trace("Catch error in a log file")
}
jdecuyper
A: 

If your trying to track down a intermittent bug, your first step is to register for the error handling events that Loader can fire. Your loader is probably experiencing periodic communication errors with the server or somesuch, and those alerts are just falling into a black hole, so your seeing this erratic behaviour.

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Loader.html#load%28%29

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/IOErrorEvent.html

JStriedl
+3  A: 

An important thing to note here is that you are most likely causing this issue. Your code is good, don't get me wrong, but it is a bad idea to iterate through an array and create loaders and load on each iteration. The following can introduce the problems you're having. Most people, including myself, use budget hosting (BLUEHOST personally), which are great for what they are, but are typically shared boxes and you want to optimize how your sites load. The way around this is quite simple.

EXPLANATION:

Instead of just iterating through an array with a for loop which is damn near to instant, we will gracefully handle each load by themselves; upon completion the next will start, until the array we are using as the dataprovider is empty. That being said, you need to create a function to start loading the first and following images.

private var images:Array = ["image1.jpg", "image2.jpg"];

private function _loadImage():void
{
    var loader:Loader = new Loader();
    var req:URLRequest = new URLRequest(images.shift()); //Removes and returns first element in an array.
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE. _onImageComplete);
}

private function _onImageComplete(e:Event):void
{
    var bmp:Bitmap = e.target.content as Bitmap;
    _someContainer.addChild(bmp);
    if(images.length > 0) _loadImage(); //Calls _loadImage function until array is empty.
}

With the above, your site should actually load faster anyhow, and it will have a nice linear effect to the load, left to right, top to bottom, or however your program your images to lay out.

ALSO:

You need to listen for asynchronous error events and catch synchronous errors. If and when an error occurs, with these handlers in place, and some intuitive code, your gallery can let itself know that there was an error and at which point the error took place; This way it can merely start loading from that place, whether it be backing up a number and restarting to iterate through an array.

I do not intend this to be insulting, because I really don't know for sure, but any flash developer should be using the Flash Player 10 Debugger, and on a side note, things like Firefox with firebug for http sniffing and etc. are musts, but in this particular case, the debugger would have told you much.

From a live trace of your site I see some interesting warnings that should probably be addressed as well.

Good luck.

Brian Hodge hodgedev.com

Brian Hodge
+1  A: 

The problem's here:

    var loader:Loader = new Loader();
    loader.load(new URLRequest(xmlSlideshow..img[i].@src));
    //trace(xmlSlideshow..img[i].@src);
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete); 
    //loader.load(imageArray[i]);

At the end of this block, the Loader object you've created goes out of scope; nothing is referring to it, so it's eligible for garbage collection i.e. at some point (unpredictably) the Flash player will clear up the memory allocated for that object.

Most of the time, GC won't kick in for a while, so your load will probably work. But sometimes, GC will kick in, and you'll lose some of those loader objects.

So - hang on to your loaders! Store them in another array (alongside your images array would be fine) and then clean them up after COMPLETE has fired on each one.

As an aside, it's always better to do this:

var loader:Loader = new Loader();
// Note the position of this line!
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete); 
loader.load(new URLRequest(xmlSlideshow..img[i].@src));

rather than this:

var loader:Loader = new Loader();
loader.load(new URLRequest(xmlSlideshow..img[i].@src));
// Note the position of this line!
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete);

because in some cases where the loading file is cached, COMPLETE will fire before you've added your listener! Make sure you add your listeners before you start the operation which might fire events, in all situations.

HTH!

Ian

IanT
Oh - as another aside, Brian is right that Flash can choke if you load too many files at the same time, and in some extreme cases actually crash the browser (I got that a lot in AS2); it's often better to queue them as he suggests, although in practice we've found that loading 5-10 concurrently is fine.
IanT
yup, listeners before load. Always be prepared. :)
Brian Hodge
A: 

Another solution might be to use QueueLoader by Hydrotik. Take a look:

http://code.google.com/p/queueloader-as3/

Works like a charm for me. Good luck.

BTW: anyone have any of those refresh issues with the flash player not firing a load COMPLETE in IE7? :)

Ben