What’s new in v2

Table of Contents

  1. Complexity reduction
  2. Signals, no Events
  3. Endless recursion of loaders within loaders
  4. Loaders can work independently
  5. Unit Testing

Complexity Reduction

v1 had too much ‘useless’ complexity, v2 simply removed this by reducing the amount of public apis and classes.

  • ILoaders are now produced from a factory, instead of the ILoadUnit.
  • ILoadUnit, ILoadGroup and more have been removed. Their functionality has been move too an appropriate place. e.g. v1 – to get an ILoader’s id, type, request, etc you had get that ILoader’s ILoadUnit instance. The two could not work without each other. v2 – if you have the ILoader, you have all the information you need and the ILoader can work on its own.
    • This also includes adding params, previously this was done on the ILoadUnit, now it’s done directly on the ILoader.
  • Child-Parent system works automatically. e.g. if you construct an ILoader instance anywhere (not by using one of IAssetLoader’s “add” methods) and you then add it to an IAssetLoader instance, the parent of the ILoader is automatically updated internally. You’ll notice that the parent property isn’t publically settable. Same is applicable for removing the ILoader from an IAssetLoader.

Δ Table of Contents

Signals, No Events

Just what it says, there are no Events being dispatched. v2 follows roughly the same model of Events by always passing a clone of the dispatched signal to the handler. These signals all extend the base signal LoaderSignal, which has one public property “loader”, which always gives you reference to the ILoader that dispatched the signal. Some signals will dispatch data with it as a second argument; these are mainly the signals containing the word “complete” in it. e.g. onComplete, onChildComplete. Also be on the lookout when a signal is not the standard LoaderSignal. E.g. ErrorSignal, ProgressSignal, etc, these carry “extra” public properties with them.

These are the three primary signals: (ASDocs explains all of them)

  • onComplete – 2 arguments : (signal, data)
  • onProgress – 1 argument : (signal)
  • onError – 1 argument : (signal)

Code speaks louder than words, so have a look at this:

var xmlLoader : ILoader = new XMLLoader(new URLRequest("gallery-config.xml"));

xmlLoader.onError.add(xmlLoader_error_handler);
xmlLoader.onProgress.add(xmlLoader_progress_handler);
xmlLoader.onComplete.add(xmlLoader_complete_handler);

xmlLoader.start();

function xmlLoader_error_handler(signal:ErrorSignal) : void
{
	trace(signal.type + " | " + signal.message);
}

function xmlLoader_progress_handler(signal:ProgressSignal) : void
{
	trace(signal.progress + "%");
}

function xmlLoader_complete_handler(signal:LoaderSignal, xml:XML) : void
{
	trace(xml);
}

As you can see the ErrorSignal and ProgressSignal carry more data with them, just to make it easier to retrieve the related data, whereas the “onComplete” LoaderSignal doesn’t, but it has the strongly typed payload.

Δ Table of Contents

Endless recursion of loaders within loaders

v1 had linear (but complex) layout → IAssetLoader contained IGroupLoaders and/or ILoaders; IGroupLoaders contained ILoaders.

v2 – IAssetLoader contains ILoaders, but IAssetLoader is also an ILoader.

Excuse the funny “non-standard” indentation; I want to make it very clear what’s going where.

//Construct primary IAssetLoader and set BASE property for all child loaders to inherit
var primaryLoader : IAssetLoader = new AssetLoader();
primaryLoader.setParam(Param.BASE, "http://some.where.com/");

//Text based group
	var textGroup : IAssetLoader = new AssetLoader("text-group");
		textGroup.addLazy("txt-01", "text/file-01.txt");
		textGroup.addLazy("txt-02", "text/file-02.txt");
		textGroup.addLazy("txt-03", "text/file-03.txt");

//DisplayObject based group
	var displayGroup : IAssetLoader = new AssetLoader("display-group");

		var imageGroup : IAssetLoader = new AssetLoader("image-group");
			imageGroup.addLazy("img-01", "images/image-01.jpg");
			imageGroup.addLazy("img-02", "images/image-02.jpg");
			imageGroup.addLazy("img-03", "images/image-03.jpg");

		var swfGroup : IAssetLoader = new AssetLoader("swf-group");
			swfGroup.addLazy("swf-01", "swfs/animation-01.swf");
			swfGroup.addLazy("swf-02", "swfs/animation-02.swf");
			swfGroup.addLazy("swf-03", "swfs/animation-03.swf");

	displayGroup.addLoader(imageGroup);
	displayGroup.addLoader(swfGroup);

//Loose loaders
primaryLoader.addLazy("gallery-config", "xml/gallery.xml");
primaryLoader.addLazy("global-css", "styles/default.css");

primaryLoader.addLoader(textGroup);
primaryLoader.addLoader(displayGroup);

primaryLoader.start();

Δ Table of Contents

Loaders Work Independently

ILoader implementations can work without having a parent to manage them. In the signals example above, we are constructing an XMLLoader straight up and using it. This functionality is useful for e.g. custom services that only loads one file. It will save you time and effort as all the possible errors are consolidated. You don’t have to add “hundreds” of event listeners to check for parsing errors, security errors, etc. You can be assured that file will arrive at your service quickly and correctly.

All the ILoader implementations can be found in the org.assetloader.loaders package. All of them can be constructed and used without a parent, except the BaseLoader, which is only the base of all them.

Here is an Interface for a Robotlegs service that will update a user’s gallery page by page.

package org.assetloader.example.services
{
	public interface IGalleryService
	{
		function update(userId : int, pageNumber : int = 0) : void
	}
}

Let’s say that we have a PHP script that retrieves the data from the database and returns it as XML.

package org.assetloader.example.services
{
	import org.assetloader.base.Param;
	import org.assetloader.loaders.XMLLoader;
	import org.assetloader.signals.ErrorSignal;
	import org.assetloader.signals.LoaderSignal;
	import org.robotlegs.mvcs.Actor;

	import flash.net.URLRequest;
	import flash.net.URLVariables;

	public class XmlGalleryService extends Actor implements IGalleryService
	{
		protected var _xmlLoader : XMLLoader;

		public function XmlGalleryService()
		{
		}

		public function update(userId : int, pageNumber : int = 0) : void
		{
			// Destroy previous loader, if it exists.
			if(_xmlLoader)
				destroyLoader();

			var request : URLRequest = new URLRequest("getGalleryConfig.php");
			var urlVars : URLVariables = new URLVariables();

			urlVars.userId = userId;
			urlVars.pageNumber = pageNumber;

			request.data = urlVars;

			_xmlLoader = new XMLLoader(request);
			_xmlLoader.setParam(Param.PREVENT_CACHE, true);

			addListeners(_xmlLoader);

			_xmlLoader.start();
		}

		protected function complete_handler(signal : LoaderSignal, xml : XML) : void
		{
			// Parse, update model, etc

			destroyLoader();
		}

		protected function error_handler(signal : ErrorSignal) : void
		{
			destroyLoader();

			// Notify that something went wrong!
		}

		protected function addListeners(loader : XMLLoader) : void
		{
			loader.onComplete.add(complete_handler);
			loader.onError.add(error_handler);
		}

		protected function removeListeners(loader : XMLLoader) : void
		{
			loader.onComplete.remove(complete_handler);
			loader.onError.remove(error_handler);
		}

		protected function destroyLoader() : void
		{
			removeListeners(_xmlLoader);
			_xmlLoader.destroy();
			_xmlLoader = null;
		}
	}
}

Δ Table of Contents

Unit Testing

AssetLoader is fully unit tested, 304 tests and counting.

Δ Table of Contents