Loading Reloaded

Announcing BulkLoader an As3 library for multiple loadings / preloadings.

Controlling loading is tedious, error prone, and each projects has such specific requirements that you end up rewriting loading code. A lot. In my last project I spent 4 hours debugging download code and promised my self I would solve this annoyance once and for all. So in the best "let me be lazy" fashion, I decided to write my final loading code.

Everybody has been there, and there are many classes around to manage loading, but I've never found one that was complete, flexible and easy enough to use. AS3 has created some kind of loading hell: so many classes to import and understand, a plethora of listeners, the need for error handling and the new API objects (Bitmap, DisplayObject) have added more corner cases to remember. Worse still, videos are still left in some twisted logic maze.

BulkLoader is my shot at trying to unify the most common cases for loading management into a reusable library for AS3.

It is licensed under an open source MIT license. Features:

  • Unified interface for different loading types.
  • Unified progress notification.
  • Events for individual items and as a group.
  • Priority.
  • Stop,resuming and removing individually as well as in bulk.
  • Configurable number of maximum connections.
  • Cache managing.
  • Statistics about loading (latency, speed, average speed).
  • Multiple kinds on progress indication: ratio (items loaded / items to load), bytes, and weighted percentage.
  • Multiple number of retries.
  • Configurable logging.
  • Video: meta data storage, streaming as soon as connection is open, sane progress handling.
  • Helpers for different kinds of contents
  • Easy memory management (releasing objects)
  • Connection pooling.

Design goals:

  • Minimal imports.
  • Few method to learn.
  • Dynamic nature: items can be added by specifying a url as a String or a URLRequest .
  • Items can be assigned an identifier key to be used on retrieval.

At a glance:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
var loader : BulkLoader = new BulkLoader("main");
loader.add("bg.jpg");
loader.add("config.xml");
loader.add("soundtrack.mp3");
loader.add("intro.flv");
loader.addEventListener(BulkLoader.PROGRESS, onProgress);
loader.addEventListener(BulkLoader.COMPLETE, onComplete);
loader.start();

function onProgress(evt : BulkProgressEvent) : void{
    trace(evt.percentLoaded);
}

function onComplete(evt : Event) : void{
    var bgBitmap = loader.getBitmap("bg.jpg");
    addChild(bgBitmap);
    var video : Video = new Video();
    video.attachNetStream(loader.getNetStream("intro.flv"));
    parseConfig(loader.getXML("config.xml"));
}
The above code in 8 lines:

  • adds 4 items with different typed to be loaded: xml, mp3, flv, jpg.
  • created listeners for progress notification and when all items are done.

I needed a class that:

  • Would wrap up errors elegantly: retries and no errors on browser tabs closed.
  • Progress that works with many simultaneous items and many simultaneous items of very different sizes
  • Would let me use (and let me know) as each item was ready, and would allow items that can be streamed (video, sound) to be consumed as soon as possible.
  • Would treat video as any kind of asset.

I am pretty happy with the results. I feel BulkLoader strikes a good balance between ease of use, flexibility and power. At work we've used it in a few projects, and users like it.

The thought of managing multiple loadings by hand again makes me shiver. It's the same feeling I got when I started to use a tweening library.

The project is hosted at google code. Right now, I believe it's very close the final API. Mostly bug fixes and other enhancements.

Links:

Thanks to:

  • Igor Almeida: my coworker who has been a thorough beta tester. A couple of months ago he wrote a loading manager class that, while has little resemblance to BulkLoader, provided many insights and a good road map of what works (and what doesn't). Igor reported bugs and gave a lot of feedback on features and ideais.
  • Zeh: in long emails Zeh has given valuable ideas and discussed a few key issues. Having Zeh give you design ideas is (to steal a phrase from Paul Graham) like having Mick Jagger playing on your son's Bar Mitzvah.'

getting a third opinion

2.
felix says at

looks very useful. cheers!

4.
zedia.net says at

I have been looking for a class like this for a long time

5.
Mr.doob says at

Looks amazing! Thanks!

But what if you have to load 2 files with the same filename but from two different folders?

Shouldn't it be better something like this: loader.getBitmap("/folder?/bg.jpg");

6.
Mr.doob says at

Ah! I see, you can define IDs for each item. Was a silly question then :P

7.
Arthur Debert says at

Hi Folks,

Thanks for the good words.

@Mr. Doob: I didn't make myself very clear, but you can specify urls as you see fit:

   loader.add("level1/bg.jpg");
   loader.add("level2/bg.jpg");
   loader.add("http://farm1.static.flickr.com/62/162850816_18821ddd6a_b_d.jpg");
   
Of, course using different id's will make your life easier. You only have to watch out if you have the same urls being used as POST requests, since those will look like the same. Then you can either use different id's or pass a URLRequest object directly and store it so it can be used to fetch the loaded content.

Cheers

9.
Admin says at

Thanks, great loader. We did add it in our bookmarks.

11.
Arthur Debert says at

Folks, I'd ask using the google's project issue tracker for suggestions and feature requests, just so that they don't get lost, but they're dutifully noted.

@paddy: This seems like a good idea. Thanks

@Brian McBride: As3 is capable of actually closing the connection, thus freeing bandwidth, which is great. Currently changing an item's priority mid flight would reflect on the queue on the next available connection, but wouldn't close a loading operation in place.

12.
Ryan says at

Thanks for sharing this is a great kit. Really useful and able to plug into many loading scenarios where multiple versions might be used on different levels of a map for instance. Right now these can be somewhat of a pain when it is done differently by everyone.

16.
JP says at

That's great! For sure I will use this class. Thanks for sharing.

17.
Arthur Debert says at

@Jaza:

Sure can, the whole story here , or the short story:

   // get progress for main video only:
   loader.get("my_video.flv").addEventListener("onProgress", onVideoProgress);
   

@P. For a variety of reasons (mostly memory management) I work hard not to expose LoadingItem instances too much. The way to get a handle of a BulkLoader instance is:

   var loader : BulkLoader = new BulkLoader("main-site");
   // later anywhere on your code you can fetch
   // a reference to this BulkLoader instance 
   // using the static function BulkLoader,getLoader:
   var loader : BulkLoader =  BulkLoader.getLoader("main-site");
   

22.
Arthur Debert says at

@ cksachdev Yup there is, just pass a LoaderContext to the props parameter, such as:

loader.add("some.swf", {context:myLoaderContext}

@Patrik: This is fixed in the newest revision, now the id property of LoadingItems is public.

@tasovi: This is a great suggestion, I just to think the interface throughly, stay tuned.

24.
Arthur Debert says at

@BFS:

An exmple fla in is the works, but untill that is ready there are snippets that illustrate very basic usage:

25.
Dominic says at

Hey Arthur, great work!

I want to use this package, but it throws an Exception.

German Error Message: TypeError: Error #1034: Typumwandlung fehlgeschlagen: flash.events::IOErrorEvent@32cb521 kann nicht in br.com.stimuli.loading.BulkErrorEvent umgewandelt werden. at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at

flash.net::URLLoader/flash.net:URLLoader::redirectEvent()

It says that its not able to convert the Event-Object to an BulkErrrorEvent-Object.

Do you have an idea on this?

27.
Arthur Debert says at

@Dominic: I believe this issue was fixed in reviision 65, can you download the latest version and try with that one?

@flayoo: What doesn't work means? You get compile errors ? Where? If you post more info, I'll fix this asap

30.
Jens Franke says at

Hej,

first of all. Thanks for that excellent package. Really great work.

I also have some problems with the Bulk-Loader an FDT 3. It's seams so that FDT coudn't parse the LoadingItem correctly.

I upload some screenshot: http://exchange.jensfranke.com/bulk_loader_error.png

31.
Arthur Debert says at

@Jens

It's better to post this on the projects bug tracker at google code, so it doesn't get lost. I've created a ticket and will be tracking this shortly. Thanks for the report.

32.
Arthur Debert says at

@Jens

It's better to post this on the projects bug tracker at google code, so it doesn't get lost. I've created a ticket and will be tracking this shortly. Thanks for the report.

@Hej: You right. I want to prepare some full fledge examples and plan to upload them shortly.

33.
Dominic Graefen says at

Thx. I thought i was having the newest one, but now it works fine.

I've got a little question: I'am preloading my contents in the queue. Is there an easy way to change an LoadingItems priority?

Or do I need to remove the item and add it again with the highest priority?

34.
Arthur Debert says at

Hi folks.

I've been receiving a lot of interesting feedback and I've had some interesting email exchanges regarding feature requests and design decision, and I thought it would be nice if those discussions were public (this blog entry is becoming unwieldy too).

Discussion List

@ Dominic:

Your question is covered here:

35.
Junio Vitorino says at

Hi Arthur Debert, firstly i'd like congratulate you by the excellent work realized in gringo and by this project now. I tried run a example with BulkLoader and i not had success. I get the error message with BulkProgressEvent, look.

1046: Type was not found or was not a compile-time constant: BulkProgressEvent.

The source was created with base in the documentation from svn.

37.
Arthur Debert says at

Hi Matt.

I've been using BulkLoader on I.E. without any issues, so I think I need a bit more information on this:

    • Which version of i.e ?
    • Can you provide a sample of the code you are working with?

As a general note, this is not be best place for bug reports or questions.

I've setup a discussion list exactly for that , so it's easier to follow. I'd ask to post questions over there.

Thanks Arthur

38.
Junio Vitorino says at

Cool, now worked here. I did a preloader for listen the BulkLoladerProgressEvent, and work like a charm.

Thanks Arthur, BulkLoader now do part of my personal class package .

39.
Matus Laco says at

Great Class, thanks a lot!

40.
Helmut Granda says at

Hi Matt, Thanks for this great class, I am running in a small dilema and that has to do with assigning the same loaded file to different elements, for example

var tire1Bitmap = loader.getBitmap("tire.jpg"); var tire2Bitmap = loader.getBitmap("tire.jpg"); var tire3Bitmap = loader.getBitmap("tire.jpg"); var tire4Bitmap = loader.getBitmap("tire.jpg");

addChild(tire1); addChild(tire2); addChild(tire3); addChild(tire4);

only "tire4" will display the image... I know i could load the same item 4 times or maybe I need to create an actual movieclip in the library add the element to that library element and then duplicate it....

Any other shortcuts or ideas?

41.
Helmut Granda says at

A correction to my previous post.. the creator's name of the Class is Arthur not Matt.... Sorry about that.

43.
tbm says at

dude your a legend.. this is just what I needed.

47.
Arthur Debert says at

@Oscar:

Sure you can, with only one caveat: if you add items to a bulk loader instance before it's finished loading, your are golden. Else, if you add an item after the bulk loader is done loading all of it's assets, you must call

<bulkLoader>.start
again, because it was stopped when all items had finished loading.

56.
cksachdev says at

Is it possible to access Symbols from a swf file which is loaded using BulkLoader ? Like using Loader class I do var abc:Class = event.target.applicationDomain.getDefinition("MySymbol") as Class; var mySquare:MovieClip = new abc() as MovieClip; addChild(mySquare);

57.
Arthur Debert says at

Folks, as stated above, this thread is way to long, and not a very good place for discussions. If possible, please direct your queries to the mailing list.

Thanks

@michael:
Sure, just use a evt.target.id

@kyle:
It already does. It just requires some attention on you part to whether you'd like to manage two queues or actually one huge queue with the priorities being shuffled.

@Romuald:
This seems way to spefic, and will only save you one line of code. ;-)

@cksachdev:
Sure is, just watch out for using the same ApplicationDomain (usuning the same Context instance), the mailing list has a few posts about this.

64.
Arthur Debert says at

Hi Martin.

This blog entry is not a very good place for posting usage questions. If you still need some assistance, the mailing list (linked above in body) is the best place for that.

Cheers Arthur Debert

69.
Valters says at

Thank you, very usable! :)

73.
Angel Romero says at

Very Nice! This is some piece of work! Thanks for your contribution. I am going to make sure my users are aware of this library.

75.
Arthur Debert says at

@Matt.

Thanks for the kind words.

I do ask, however, to point usage questions to the mailing list , as it is a much better venue for this.

Cheers Arthur Debert

78.
Michael Hoskins says at

Might want to run stripslashes() on your code there. I see all the quotation marks prefaced by backslashes.

79.
Arthur Debert says at

@Michael:

Thanks for the heads up!

83.
aleksey says at

_bulkLoader.add("http://example.ru/manager/?xml", {id:"managerXml"});

_bulkLoader.start();

var mXML : XML = _bulkLoader.getXML("managerXml");

Error: [BulkLoader] Failed to get content with url: 'managerXml'as type: [class XML]

How load this xml?

posted by
Arthur Debert

on

Tagged with:

85 comments so far.
Say something

Other months availabe in 2007

The complete blog archive

The latest entries

Subscribe to comments on this entry: rss feed

Cloud me:
  • Rafael Cordoba in The Web does not need flash. on

    I think Flash has great potential when used the right way. A Flash application/website is supposed to be an experience for the user, the focus is not pure content.

    ...

  • ash in The Web does not need flash. on

    I've been a Flash/Flex developer for several years. I love the development environment and the pay cheque. However, every Flash/Flex developer I talk to agrees that Flash's days are numbered.

    ...

  • Gabriel Laet in The Web does not need flash. on

    @Carlos I agree with you about 2D games. But the thing is that Flash is not the only tool for that, even Unity3D is a great tool for 2D games. ...

  • Carlos Nazareno in The Web does not need flash. on

    @Gabriel, Unity3D is fantastic, but only for 3D. You need to re-think your views about games. 3D is not the be-all and end-all of gaming. Far from it, as the ...

  • Ricardo in The Web does not need flash. on

    I fully disagree. Flash is years ahead HTML 5 and all it´s infinite coming bugs across the different browsers. Flash continues to evolve features and performance as well. Besides of ...

Feeds: Entries rss feed Linksrss feed Worksrss feed

A Django joint. hosted on Slicehost