Tutorial Details
• Difficulty: Intermediate
• Program: Flash
• Estimated Completion Time: 30 mins
This entry is part 3 of 4 in the series Allen Chou's Command Pattern Tutorials

It’s very common to load external data (such as SWF files) during runtime, but only when the data is completely loaded can we read or manipulate its content. Usually we have to listen to the complete event dispatched by a Loader or URLLoader object that loads the data for completion handling. Oftentimes, we write code that loads the data in one function, and write code that handles the completion of the loading in another function, but this can be improved by grouping the whole loading process together..

This tutorial demonstrates how to create a loading extension to the command framework in my previous tutorial, Thinking in Commands part 1 of 2, to pack the loading the completion handling into one place. This loading extension can also be combined with the scene management framework covered in Thinking in Commands part 2 of 2. Many classes used in this tutorial are covered in the previous tutorial, so I highly recommend that you read the previous tutorials before going on.

Additionally, this tutorial introduces the concept of data manager, a central “bank” that stores references to data objects. You can register data to the data manger with a unique key string, and later access the data by providing the corresponding key string. This spares you the trouble of keeping references of data objects and some variable scope issues.

By the way, you’ll need the GreenSock Tweening Platform in order to complete these examples.

Normally, we handle the loaded data inside the complete event listener function. This breaks apart two chunks of code that are logically connected. And by looking at the code, your flow of thought might be interrupted as your sight jumps from the loading function to the complete event listener.

Let’s look at the logic flow of a naive SWF loading approach.

The loader loads a SWF from a URL, and the onComplete() function is invoked by the dispatchEvent() method that dispatches a complete event, where the dispatchEvent() method is invoked internally by the loader. Well, actually, it’s invoked by the LoaderInfo object that belongs to the Loader object, but for simplicity, let’s just say the dispatchEvent() method is invoked by the Loader.

Next, within the onComplete() function, the doMoreStuff() function is invoked after the loading completion handling is done and, as the function’s name suggests, does more stuff.

The high-level logic flow is very linear: invoke the Loader.load() method first, onComplete() second, and doMoreStuff() third. However, as you’ll notice from the diagram, each function’s invocation is embedded within the function body of the previous one, resulting in a “nested” code. In my own opinion, if the logic flow of a certain functionality is linear, the associated code should be written in a linear manner, not nested. Otherwise, the code could sometimes become confusing if the invocation nest level is too high.

This is when the Command approach comes into play. From the diagram below, we can see that the code is pretty linear using commands, in that all the commands are linearly chained together by a serial command. Although the program “diverts” into the setProperties(), addChildLoader(), and doMoreStuff() functions; their invocation is linear.

Data Manager

Alright, before we get down to anything further about loading, let’s first take a look at the DataManager class. A data manager lets you associate a key string with a data object, and you can obtain a reference to this data object everywhere in your code. With the data manager, you don’t have to worry about keeping data references and variable scopes. All you have to do is register a piece of data to the manager with a key string.

The coding is pretty straightforward, as shown below:

package data {
import flash.utils.Dictionary;

public class DataManager {

//a dictionary that maintains the string-data relations
private static var _data:Dictionary = new Dictionary();

//returns the data object associated with a key string
public static function getData(key:String):* {
return _data[key];
}

//registers a data object with a key string
public static function registerData(key:String, data:*):void {
_data[key] = data;
}

//unregisters a key string
public static function unregisterData(key:String):void {
delete _data[key];
}

//unregisters all key strings
public static function clearData():void {
for (var key:String in _data) {
delete _data[key];
}
}
}
}


So when we want to register a key string “myData” with a data object – say, a sprite – we could write the code as follows:

var sprite:Sprite = new Sprite();
DataManager.registerData("myData", sprite);


Later, anywhere in the code, we could write the following code to obtain a reference of the sprite and add it to a display list. It’s that simple, no more issues about maintaining object references and variable scopes.

var sprite:Sprite = DataManager. getData("myData") as Sprite;


Step 1: Create a Flash Document

Open Flash and create a new Flash Document.

Step 2: Create a Progress Bar

Draw a progress bar on the stage; this is for representing the loading progress. Convert the entire progress bar into a symbol and give it an instance name of “progressBar_mc”. Within the progress bar symbol, convert the inner progress bar into another symbol, and give it an instance name of “innerBar_mc”.

Step 3: Prepare the Images

Place three images in the same folder as the FLA file, named “image1.jpg”, “image2.jpg”, and “image3.jpg”. Here’s what the three images look like.

Step 4: Create the Document Class

Create a new AS file for the document class for the FLA file. The code is pretty straightforward, and all the details are explained in the comments. First, three loaders are created and the loading begins. On each progress event, the progress bar is updated. When the loading is complete, the progress bar fades out and the three images fade in one-by-one.

package {
import com.greensock.TweenMax;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.URLRequest;

//shrink progress bar to zero scale
progressBar_mc.innerBar_mc.scaleX = 0;

}

private function onProgress(e:ProgressEvent):void {

var bytesTotal:uint = 0;

//update progress bar scale
}

private var _completeCount:int = 0;
private function onComplete(e:Event):void {
_completeCount++;
if (_completeCount < 3) return;

//remove progress listeners

//remove completion listeners

image1.x = 30, image1.y = 30;
image2.x = 230, image2.y = 30;
image3.x = 430, image3.y = 30;

TweenMax.to(progressBar_mc, 0.5, {autoAlpha:0, blurFilter:{blurX:20, blurY:20}});

TweenMax.from(image1, 0.5, {delay:0.5, alpha:0, blurFilter:{blurX:20, blurY:20}});
TweenMax.from(image2, 0.5, {delay:0.7, alpha:0, blurFilter:{blurX:20, blurY:20}});
TweenMax.from(image3, 0.5, {delay:0.9, alpha:0, blurFilter:{blurX:20, blurY:20}});
}
}
}


Step 5: Test the Movie

Press CTRL+ENTER to test the movie. You’ll see that the progress bar immediately fades out and the three images fade in. That is because the images are local files, meaning they can be loaded almost immediately. To simulate online download speed, first select the View > Download Settings > DSL as the simulated download speed, and then press CTRL+ENTER again without closing the test window to start simulating online downloading. This time you shall see the progress grow progressively wider before it fades out.

Okay, it’s time to load the images with the command framework.

Utility Commands

Before we proceed, let’s create some utility commands that will be used later in the example. Again, these command classes are based on the command framework presented in my previous tutorial (Part 1), and I highly recommend that you go through them before going on. If you’ve read the tutorial before, you can always head back if you need your memory refreshed.

Data Managers Commands

Here we are going to create two commands for registering and unregistering data for the data manager class. The RegisterData command registers data to the manager, while the UnregisterData command unregisters data.

package commands.data {
import commands.Command;
import data.DataManager;

//this command registers data to the data manager
public class RegisterData extends Command {

public var key:String;
public var data:*;

public function RegisterData(key:String, data:*) {
this.key = key;
this.data = data;
}

override protected function execute():void {
DataManager.registerData(key, data);
complete();
}
}
}

package commands.data {
import commands.Command;
import data.DataManager;

//this command unregisters data from the data manager
public class UnregisterData extends Command {

public var key:String;

public function UnregisterData(key:String) {
this.key = key;
}

override protected function execute():void {
DataManager.unregisterData(key);
complete();
}
}
}


This command encapsulates a Loader instance’s load() method. You may provide an onProgress command that is executed upon each progress event and an onComplete executed when the loading is complete. Note that the complete() method is invoked when the loading is complete. This line of code is extremely crucial. If you do not invoke the method, the command will never be regarded as complete, jamming your entire application in the worst case scenario.

package commands.loading {
import commands.Command;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.URLRequest;

public var url:URLRequest;

public var onProgress:Command;
public var onComplete:Command;

this.url = url;
this.context = context;
this.onProgress = onProgress;
this.onComplete = onComplete;
}

override protected function execute():void {

}

//remove listeners

complete();
}

private function progressListener(e:ProgressEvent):void {

//execute the onProgress command
if (onProgress) onProgress.start();
}

private function completeListener(e:Event):void {

//execute the onComplete command
if (onComplete) onComplete.start();
}
}
}


The InvokeFunction Command

This command encapsulates the invocation of another function. It is designed to allow you to provide an extra parameter array for the function to be invoked.

package commands.utils {
import commands.Command;

//this command invokes a function
public class InvokeFunction extends Command{

public var func:Function;
public var args:Array;

public function InvokeFunction(func:Function, args:Array = null) {
this.func = func;
this.args = args;
}

override protected function execute():void {
func.apply(null, args);
complete();
}
}
}


That’s it. Time for the example.

Step 1: Copy the Flash Document File

Copy the FLA file from the previous example to a new folder and copy the image files along with it.

Step 2: Create the Document Class

Create a new AS file for the document class of the copied FLA file, named “LoadingDataWithCommands”. Remember to change the document class name in the FLA file to this new one.

The code for the document class is pretty clean. It simply sets the current scene to a LoadingScene with a scene manager. We are using the scene framework presented in my previous tutorial (Part 2). You can check it out if you’ve forgotten how to use it.

package  {
import flash.display.MovieClip;
import scenes.SceneManager;

var sceneManager:SceneManager = new SceneManager();
}
}
}


Extend the Scene class to create a new class named LoadingScene. The container property holds a reference to the main sprite. This allows us to access the progress bar later.

package {
import scenes.Scene;

this.container = container;
}
}
}


Now, create the intro command for the loading scene. The intro will create three loaders and begin the loading process. This is done by overriding the createIntroCommand() method. The following code goes into the class body, same as the constructor.

//the intro command begins the loading of the three images
override public function createIntroCommand():Command {

var command:Command =
new ParallelCommand(0,

//shrink the progress bar to zero scale
new SetProperties(container.progressBar_mc.innerBar_mc, {scaleX:0}),

new SerialCommand(0,

//registers the three loaders to the data manager
new ParallelCommand(0,
),

new ParallelCommand(0,
new InvokeFunction(onProgress) //onProgress command
),
new InvokeFunction(onProgress) //onProgress command
),
new InvokeFunction(onProgress) //onProgress command
)
)
)
);

return command;
}


Next, override the onSceneSet() method. This method is invoked when the intro command is complete, indicating that the loading is complete. Within this method, we tell the scene manager to transit to the main scene. Before the scene transition, the outro command is executed first.

override public function onSceneSet():void {
sceneManager.setScene(new MainScene(container));
}


And then override the createOutroCommand. This command shall fade out the progress bar.

//the outro command fades out the progress bar
override public function createOutroCommand():Command {
var command:Command =
new SerialCommand(0,

new TweenMaxTo(container.progressBar_mc, 0.5, {autoAlpha:0, blurFilter:{blurX:20, blurY:20}}),

//remove progress bar from display list
new RemoveChild(container, container.progressBar_mc)
);

return command;
}


Finally, create the onProgress method invoked by the InvokeFunction commands.

private function onProgress():void {

//retrieve loader references from the data manager

var bytesTotal:uint = 0;

//update progress bar scale
}


Step 4: The Main Scene

Now create a new class for the main scene, extending the Scene class.

package {
import scenes.Scene;

public class MainScene extends Scene {

this.container = container;
}
}
}


Override the createIntroCommand() method. This method will add the loaders to the display list, and fade them in one-by-one. In addition, the data key strings are unregistered from the data manager.

override public function createIntroCommand():Command {

//retrieve loader references from the data manager

var command:Command =
new ParallelCommand(0,

new SerialCommand(0,

new ParallelCommand(0,
),

new ParallelCommand(0,
),

new ParallelCommand(0,
new TweenMaxFrom(loader2, 0.5, {delay:0.2, alpha:0, blurFilter:{blurX:20, blurY:20}}),
new TweenMaxFrom(loader3, 0.5, {delay:0.4, alpha:0, blurFilter:{blurX:20, blurY:20}}),
)
),

//unregsiter data from the data manager
new ParallelCommand(0,
)
);

return command;
}


Step 5: Test the Movie

Alright. We’re done! Test the movie and simulate online downloading. You will see the exact same result as in the previous example, but this time it’s all done with the command framework and the scene framework.

Summary

In this tutorial, I’ve shown you how to load external images with the command framework. The LoaderLoad command can be used to load external SWF files, too. Moreover, you can create your own commands to load external data other than images and SWF files, by encapsulating the URLLoader class into your commands.

We’ve written more code in the second example than the first one. Remember, the purpose of using the command framework and the scene framework is not to achieve the same result with less code, but to manage the code in a systematic and modular approach, making your life easier when it comes to future maintenance and modification.

The first example squeezes all the code into one single class, making it difficult for future maintenance if the code amount should grow extremely large. The second example, on the other hand, separates logically independent code into different scenes, making it easier for future modification. Also, by integrating with the command framework and the scene framework, we’ve made room for future extension, where we can add more scenes and intro/outro commands without disrupting irrelevant code.

This is the end of this tutorial. I hope you enjoyed it. Thanks for reading!

Other parts in this series:Managing Sounds with Commands»

• Rich

The command pattern can be really useful and if applied correctly can really help to decouple your application. I think there’s some good info here, but some of it is a bit confused.

For example, what’s the utility of your DataManager class? IMO all this is doing is making your application reliant on global variables and static functions, both of which should be avoided. Furthermore, as it returns a wild-card it removes strong typing and will introduce the need to caste all your objects. This is really bad practice and would make building large modular applications extremely difficult.

Also, things like this are completely unnecessary:

//remove progress bar from display list
new RemoveChild(container, container.progressBar_mc)

Not only does this unnecessarily complicate things, but it also tightly couples the class that instantiates the command to the command. The amount of times ‘new’ is used should be a good indication that there’s a lot of coupling being introduced between classes.

Commands can be a really good way to separate out blocks of logic and decouple the different parts of your application, but they shouldn’t be used for every thing.

• http://cjcat.blogspot.com Allen Chou

I think you’re right about the global variable thing.

When I was writing the data manager, I was actually thinking the Proxy class in PureMVC. I thought it acts like a global data aggregator, in that this is how you obtain a reference to a proxy object.

var proxy:MyProxy = Facade.getInstance().retrieveProxy(proxyName) as MyProxy;

In this case casting is also necessary. Actually, I also find the necessity for the casting throughout an application not friendly, but so far this is what I can come up with. Any suggestions?

As for the RemoveChild tightly-coupling thing, I wasn’t aware of the problem during the writing. Do you think it’s better to encapsulate the child removal in the a method in the container class, and invoke that method externally, say, by using the InvokeFunction command?

Thanks for the comments. I’ll be sure to consider these issues when writing future tutorials.

Oh, and just one more thing. There are tight couplings between the command subclasses and the scene subclasses. But what I intended was that, I wanted to limit the tight couplings up to the scene classes. If I want to swap inter-scene behaviors, I could just swap in another scene subclass that overrides the createIntroCommand(), createOutroCommand(), and onSceneSet() methods differently. Or, I could further encapsulate common commands into composite commands, and can be easily swapped with new ones within scene subclasses. Any ideas?

• rich

You’re right, it is used in the PureMVC framework, but that’s one of the reasons why people are increasingly moving away from it and towards newer frameworks like Robotlegs and Parsley. I’d recommend looking into Robotlegs as it can be used in a similar way to PureMVC, but has a far more elegant solution for retrieving framework actors and isn’t based on singletons that can make large PureMVC apps quite complicated.

http://github.com/robotlegs

http://martinfowler.com/articles/injection.html

In regards to removing coupling between you commands, I think a lot of what you’re trying to do shouldn’t be using the command pattern in the first place. InvokeFunction for example, why not just invoke the function? By utilising the apply arguments method you’re again removing strong typing without any need.

There are lots of other patterns available, some of which might better suit what you’re trying to achieve here. I’d have a look at the strategy pattern which uses composition to change a classes behavior at run time. If you do want to stick with using the command pattern this way then you could think about introducing a CommandFactory class that would delegate the instantiation of the commands. That way the classes would only be coupled to the factory and you could swap out factories as long as they implement the same interface. You’ll always have coupling in between classes, but using the right patterns will allow you to control it.

• Rich

You’re right, it is used in the PureMVC framework, but that’s one of the reasons why people are increasingly moving away from it and towards newer frameworks like Robotlegs and Parsley. I’d recommend looking into Robotlegs as it can be used in a similar way to PureMVC, but has a far more elegant solution for retrieving framework actors and isn’t based on singletons that can make large PureMVC apps quite complicated.

http://github.com/robotlegs

http://martinfowler.com/articles/injection.html

In regards to removing coupling between you commands, I think a lot of what you’re trying to do shouldn’t be using the command pattern in the first place. InvokeFunction for example, why not just invoke the function? By utilising the apply arguments method you’re again removing strong typing without any need.
There are lots of other patterns available, some of which might better suit what you’re trying to achieve here. I’d have a look at the strategy pattern which uses composition to change a classes behavior at run time. If you do want to stick with using the command pattern this way then you could think about introducing a CommandFactory class that would delegate the instantiation of the commands. That way the classes would only be coupled to the factory and you could swap out factories as long as they implement the same interface. You’ll always have coupling in between classes, but using the right patterns will allow you to control it.

• http://cjcat.blogspot.com Allen Chou

Right. A command factory can be useful. Actually, I’m trying to use the createIntroCommand() and createOutroCommand() methods as my factory methods. Instead of swapping the factory objects, in my case, I can swap scene objects. But I think you’re right. Using factories does make the classes even more loosely coupled than using factory methods.

I’ll try to redesign the framework if I’ve got time. Thanks for the comments.

• http://cjcat.blogspot.com/ Allen Chou

Guess what? It turned out that some people are actually complaining about the overly casting issue in PureMVC.

It seems that one of the preferred solution is the Dependency Injection pattern, as described in the article.

Robotlegs seems to avoid this casting problem by using injection metadata tags. I’ll definitely survey more about the Robotlegs and the pattern.

http://www.robotlegs.org/

• vitaLee

you have a typo in the third code sample

var sprite:Sprite = DataManager.registerData(“myData”) as Sprite;

i believe you meant to type DataManager.getData(“myData”) as Sprite; .

• http://cjcat.blogspot.com/ Allen Chou

Yeah, you’re right. I’ve already sent a mail to ActiveTuts+ about the typo. It shall be fixed in no time. Thanks for pointing out.

• http://snaptin.com Ian Yates
Staff

Good spot – typo corrected :)

• Enrique

Hi Allen!!
#
# //remove listeners
#
# complete();
# }

you are removing the:

How do you know which function will be executed first (loadingComplete or completeListener)?
I mean, if loadingComplete is executed before completeListener, then completeListener won’t be executed because you have removed their listener.

• http://cjcat.blogspot.com/ Allen Chou

Ah, yes. Thanks for pointing it out.

If I remember correctly, event listeners of the same priority are executed in the order they are registered to the event dispatcher. But I think a safer and better way to manage the execution order is explicitly specify the listener’s priority, which is one of the parameters passed to the addEventListener() method.

You’re right, the code presented here is a little confusing. You can specify the listeners’ priority.

• Marcus Olley

Hi Allen,

Can you please tell me how I can apply this to make a website. I am very new to AS3.