Using Metadata Frame for a Preloader

This article was sleeping in my drafts for a while, and I am happy I managed to finish it today. There are multiple ways to create preloader for your ActionScript applications with flex compiler. The easiest and my prefered way is to use Frame metadata.

This metadata is a hint to the compiler that the class containing the metadata would like to be bootstrapped by the cited factory. In other words, when you build an application based on mx.core.Application, that isn’t actually the “root” class of the SWF. The root class is actually a compiler-generated subclass of mx.managers.SystemManager (Modular Applications)

Using it as a preloader is very easy thing, because you can apply it on your existing projects without almost any intervention with the original code. Open you main application class and add Frame metadata before class definition:

[Frame(factoryClass="sk.yoz.myapp.Preloader")]
public class MyApp extends Sprite
{
    public function MyApp(preloader:Preloader)
    {
        ...

What it does is, that your class is not manufactured by default but it is waiting until factory class does it. In our case manufacture class is a preloader.

package sk.yoz.myapp.preloader
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.utils.getDefinitionByName;

	public class Preloader extends Sprite
	{
		public function Preloader()
		{
			super();
			stage.align = StageAlign.TOP_LEFT;
			
			updateProgress();
			addEventListener(Event.ENTER_FRAME, updateProgress);
			stage.addEventListener(Event.RESIZE, updateProgress);
			loaderInfo.addEventListener(ProgressEvent.PROGRESS, updateProgress);
			loaderInfo.addEventListener(Event.COMPLETE, onComplete);
		}
		
		private function updateProgress(... rest):void
		{
			trace(loaderInfo.bytesLoaded / loaderInfo.bytesTotal);
		}
		
		private function onComplete(event:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, updateProgress);
			stage.removeEventListener(Event.RESIZE, updateProgress);
			loaderInfo.removeEventListener(ProgressEvent.PROGRESS, updateProgress);
			loaderInfo.removeEventListener(Event.COMPLETE, onComplete);
			
			var app:Class = getDefinitionByName("MyApp") as Class;
			addChild(new app(this));
		}
	}
}

Very important thing to notice here is, that your MainApp class instance does not have stage property available until its added on stage. So you can not access stage property directly in constructor but you have to define event handler for Event.ADDED_TO_STAGE.

Where to go from here:

5 comments so far

  1. karim January 5, 2011 18:10

    Learned something here – that’s brilliant, and usefull. Thanks for sharing.

  2. Stepan January 10, 2011 21:37

    I use a similar aproach, however I think the Preloader has to extend MovieClip. At least in my case the Sprite-based preloader throws an error when I attempt to instantiate the app main class form the onComplete handler.

  3. Jozef Chúťka January 11, 2011 15:37

    @Stepan, for my apps I usualy use Sprite for app as well as for preloader. works fine, no errors thrown. Well, I usualy use it this way:
    var app:MyApp = new MyApp(this);
    addChild(app);

  4. [...] reading this post here – I was keen to try using the [Frame(factoryClass="MyPreloader")] technique on some [...]

  5. [...] Using Metadata Frame for a Preloader [...]

Leave a comment

Please be polite and on topic. Your e-mail will never be published.