Flash/Actionscript 3: Inversion of Control pattern demonstration

By creating a series of Actionscript 3 demonstrations, I hope to showcase the sophistication of the Flash platform by sharing some of the more useful and unusual techniques that are possible. While I am a web standards advocate, the software developer in me still enjoys building for the Flash platform. I can’t help but feel bittersweet about the slow decline of the Flash platform as it makes way for more standardized technologies like HTML5 and Javascript. Actionscript 3 is a pleasure to develop with, and has features that lend themselves well to type-safe, structured, team development.

My first demonstration will be a simple implementation of the Inversion of control principle in Flash.

What is Inversion of Control?

The Java community is buzzing with the concept of IOC or “Inversion of Control”. In simple terms, Inversion of Control is a principle where a program’s centralized code no longer controls it’s behavior. Instead, the program receives it’s flow from an outside source. In practice, the outside source is usually an XML configuration file. The XML config is often loaded at the start of program execution, and the program takes different actions at runtime based on the information contained in the configuration file.

IOC has many applications, but a common use is to specify an object’s class in XML rather than hard-coding specific classes in source code. IOC can add flexibility to your applications by allowing you to swap out which classes are instanced at runtime, without the need to re-compile and re-deploy your whole application.

Download the source files for this tutorial here

library.fla

In the FLA folder, you will find Library.fla. In the library, you will find two movie clips of interest, “linear” and “path”. Note the linkages of these two movie clips. Feel free to drill down into each of these movie clip’s timelines and note how their animations differ. This FLA is set to publish to a SWF called lib.swf (exported to bin-debug).

Linked Movie Clips from Library.fla

config.xml

In the bin-debug/xml folder, you will find a file called config.xml. Note how the “movies” node contains two “movie” nodes. Observe how each movie node’s text is set to the linkage identifiers that are set in Library.fla.

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <libraries>
    <library path="lib.swf">
      <movies>
        <movie x="206" y="0"><![CDATA[com.glowfilter.animation.timeline.Linear]]></movie>
        <!--movie x="206" y="0"><![CDATA[com.glowfilter.animation.timeline.Path]]></movie-->
       </movies>
    </library>
  </libraries>
</data>

IOC.as

In the top level of the src folder, you will find the IOC.as class. This is the main document class and is responsible for loading our config.xml, loading our lib.swf, and creating instances of our movie clips from lib.swf. The classes that are instantiated are specified in config.xml.

Step 1: Load config.xml

After our constructor is called, and we are added to the stage, we load config.xml in the loadConfig() method.

//Constructor is called first
public function IOC()
{
	this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage,false,0,true);
}

private function onAddedToStage(event:Event):void{
	this.removeEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
	this.loadConfig();

}

private function loadConfig():void{
	var loader:URLLoader = new URLLoader();
	loader.addEventListener(Event.COMPLETE, xmlLoaded, false,0,true);
	//Step 1: Load config file
	loader.load(new URLRequest("xml/config.xml"));
}

Step 2: Load lib.swf

When our config.xml file is fully loaded, we then load in lib.swf. If you recall, this is the library that contains our animations that are exported for Actionscript.

private function loadLib():void{
	var libLoader:Loader;
	var req:URLRequest = new URLRequest(library);

	var context:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);

	libLoader = new Loader();
	libLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLibLoaded,false,0,true);
	//Step 2: make request for library lib
	libLoader.load(req,context);
}

private function onLibLoaded(event:Event):void{
	event.target.removeEventListener(Event.COMPLETE,onLibLoaded);
	initLibraryAnimations();
}

Step 3: Initialize our classes specified in config.xml

We use Flash’s getDefinitionByName() method to create instances of the classes named in config.xml. Once the classes are instantiated, we add them to the stage, and place them on the proper x and y coordinates (also specified in config.xml).

Now open up Main.fla and run the program. You will see the “linear” animation play out. Try commenting out line 6 of config.xml and un-commenting line 7 and run the app again. You will now see the “path” movie clip play out that we created in lib.fla. What is really worth noting, is that we have changed the course of the program by changing out which animation class gets instanced at runtime.

private function initLibraryAnimations() : void
{
	//Step 3 Dynamically create the movie clip animations using classes specified in XML
	var definition:String;
	definition = xml.libraries.library.movies.movie[0];
	//This is where the magic happens. Flash's getDefinitionByName() function
        //allows us to create class instances from their String names
	var MovieClass:Class = getDefinitionByName(definition) as Class;
	var tmpMovie:* = new MovieClass();
	tmpMovie.x = xml.libraries.library.movies.movie[0].@["x"];
	tmpMovie.y = xml.libraries.library.movies.movie[0].@["y"];
	addChild(tmpMovie);
}

Conclusion

Although this is a basic example, this method can be further expended and made useful in a more complex application. For instance, a server generated config.xml file loaded into the application at runtime can create instances of certain classes based on user preferences. This behavior can also be useful in a team environment where each developer is working with separate library FLA documents, and the contents of each developer’s FLA files can be shared and easily configured. This example can also be further expanded to allow for better type safety.

That’s it for this tutorial. Check back soon for my next demonstration of the capabilities of Flash and Actionscript 3.

blog comments powered by Disqus