Follow Flex After Dark on Twitter

Flex Modules

Flex Modules are code functionality compiled to dynamically-loadable SWF files that can be loaded and unloaded by an application at run-time.

Modules let you split your application into several pieces, or modules. The main application, or loader, can dynamically load other modules that it requires, when it needs them. It does not have to load all modules when it starts, nor does it have to load any modules if the user does not interact with them.

Any number of applications can share a module, but a module cannot be run by itself, independently of an application.

Modules API

Flex's Module API defines...

  • IModuleInfo - a handle for a module, provides information such as url and load state
  • Module - base class for MXML-based modules
  • ModuleBase - base class for ActionScript-based modules
  • ModuleLoader - loads modules dynamically at run-time
  • ModuleManager - singleton, centrally manages dynamically loaded modules
  • ModuleEvent - dispatched for events in the module lifecycle

Module-related ActionScript classes are defined in the mx.modules package. (The ModuleEvent class is defined in the mx.events package.)

Creating Modules with MXML and ActionScript

The examples below show how to define Modules using MXML and ActionScript. However, inside the <mx:Module> and SampleModule class definitions there really isn't any code defined. This is because aside from extending one the base Module classes there isn't any other code or contract your modules must implement; they're just like any other component.

MXML-based Modules

Modules are defined in MXML using the <mx:Module> tag.

   <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
      width="100%" height="100%">
      ...
   </mx:Module>

ActionScript-based Modules

   import mx.modules.ModuleBase;
   
   public class SampleModule extends ModuleBase
   {
      ...
   }

Aside from extending one the base Module classes there isn't any other code or contract your modules must implement; they're just like any other component. The key to modules is not how the are created, but how they are loaded.

Loading Modules

Modules are dynamically loaded (and unloaded) at run-time over the network. Both the ModuleManager and ModuleLoaders can be used to load modules.

When an application no longer needs to use a loaded module, it can unload it to free up memory and resources.

Module Manager (mx.modules.ModuleManager)

The ModuleManager (mx.modules.ModuleManager) class manages dynamically loaded modules. The ModuleManager class provides a lower-level API for handling modules than the ModuleLoader class (below).

The ModuleManager is a singleton and is primarily used via the static getModule() function. The getModule() function accepts a URL argument and returns an IModuleInfo instance.

   var moduleInfo:IModuleInfo = ModuleManager.getModule( "SampleModule.swf" );
   
   moduleInfo.addEventListener( ModuleEvent.READY, onModuleReady );
   
   moduleInfo.load();

When a Module is loaded and ready, get an instance using IModuleInfo's factory create() method.

   protected function onModuleReady( moduleEvent:ModuleEvent ):void
   {
      var moduleInfo:IModuleInfo = moduleEvent.module;
      
      var sample:SampleModule = moduleInfo.factory.create() as SampleModule;
   }

Module lifecycle and status updates are delivered via events to listeners registered with the ModuleManager.

Commonly used ModuleManager events:

  • loading (FlexEvent.LOADING) - dispatched when the ModuleLoader starts to load a URL
  • progress (ModuleEvent.PROGRESS) - dispatched at regular intervals as the module loads
  • ready (ModuleEvent.READY) - dispatched when the module is finished loading
  • error (ModuleEvent.ERROR) - dispatched when the module throws an error
  • unload (ModuleEvent.UNLOAD) - dispatched when the module data is unloaded
  • setup (ModuleEvent.SETUP) - dispatched when information about the module is available but not yet ready
  • urlChanged (FlexEvent.URL_CHANGED) - dispatched when the ModuleLoader is given a new URL

Module Loader (mx.modules.ModuleLoader)

A ModuleLoader (mx.modules.ModuleLoader) class instance is used for loading a single Module.

A ModuleLoader ensures that only a single copy of a module SWF file is transferred over the network by using the ModuleManager.

Commonly used ModuleLoader properties:

  • url:String - the url location of the module

Commonly used ModuleLoader methods:

  • loadModule():void - loads the module
    • url:String (optional) - value to set and use for the modules url
    • bytes:ByteArray (optional) - a byte array with the contents of a compiled SWF module
  • unloadModule():void - unloads the module

Commonly used ModuleLoader events:

  • loading (FlexEvent.LOADING) - dispatched when the ModuleLoader starts to load a URL
  • progress (ModuleEvent.PROGRESS) - dispatched at regular intervals as the module loads
  • ready (ModuleEvent.READY) - dispatched when the module is finished loading
  • error (ModuleEvent.ERROR) - dispatched when the module throws an error
  • unload (ModuleEvent.UNLOAD) - dispatched when the module data is unloaded
  • setup (ModuleEvent.SETUP) - dispatched when information about the module is available but not yet ready
  • urlChanged (FlexEvent.URL_CHANGED) - dispatched when the ModuleLoader is given a new URL

ModuleLoader ActionScript Example

Use the ModuleLoader class directly to load a Module using ActionScript.

   import mx.events.ModuleEvent;
   import mx.modules.ModuleLoader;
   
   public function loadSampleModule():void
   {
      // the url to the module can be relative or absolute
      var moduleUrl:String = "SampleModule.swf";
      
      var loader:ModuleLoader = new ModuleLoader( moduleUrl );
      
      // register event listeners
      loader.addEventListener( ModuleEvent.PROGRESS, handleModuleProgress );
      loader.addEventListener( ModuleEvent.READY, handleModuleReady );
      loader.addEventListener( ModuleEvent.ERROR, handleModuleError );
      
      // start the module loading
      loader.load();
   }

Below you will find examples of event handler functions for ModuleEvents (in the Module Events example section).

ModuleLoader MXML Example

Use the <mx:ModuleLoader> tag to load a Module using MXML.

   <!-- Load module with event handlers for progres, ready, and error. -->
   <mx:ModuleLoader url="SampleModule.swf"
      progress="handleModuleProgress(event);"
      ready="handleModuleReady(event);"
      error="handleModuleEvent(event);"
   />

Below you will find examples of event handler functions for ModuleEvents (in the Module Events example section).

Module Events

Module Events (mx.events.ModuleEvent) are fired during a Module's lifecycle by ModuleLoader and ModuleManager.

ModuleEvent types defined as static properties:

  • PROGRESS ("progress") - dispatched when the module is in the process of downloading
  • READY ("ready") - dispatched when the module has finished downloading
  • ERROR ("error") - dispatched when there is an error downloading the module
  • UNLOAD ("unload") - dispatched when the module is unloaded
  • SETUP ("setup") - dispatched when enough of a module has been downloaded that you can get information about the module

ModuleEvent properties (inherited from ProgressEvent):

  • module:IModuleInfo - information about the module
  • bytesLoaded:Number - number of items or bytes loaded
  • bytesTotal:Number - total number of items or bytes that will be loaded if the loading process succeeds

Example Module Event Handlers

The following code shows an example of what a Module event handler could look like for the above examples.

   // handle ModuleEvent.PROGRESS
   protected function handleModuleProgress( moduleEvent:ModuleEvent ):void
   {
      // update a ProgressBar control
      progressBar.setProgress( moduleEvent.bytesLoaded, moduleEvent.bytesTotal );
   }
   
   // handle ModuleEvent.READY
   protected function handleModuleReady( moduleEvent:ModuleEvent ):void
   {
      // let the user know the module was loaded
      progressLabel.setText( "Module completed loading: " + moduleEvent.bytesTotal + " bytes" );
   }
   
   // handle ModuleEvent.ERROR
   protected function handleModuleError( moduleEvent:ModuleEvent ):void
   {
      // throw an error
      throw new Error( "Module error loading: " + moduleEvent.module.url );
   }

Passing query string data to Modules

Query string parameters (e.g. ?param=value) can be appended to the URL used to load a Module.

   <!-- Load module with query parameters on the URL. -->
   <mx:ModuleLoader url="SampleModule.swf?firstName=Joe&lastName=Public" />

The query string parameters can then be accessed in the Module using its loaderInfo property. (Unfortunately the parameters must be parsed manually in ActionScript.)

The below example shows how to access and parse the query string parameters passed in the URL used to load a module.

   public function getQueryParams():Object
   {
      var url:String = this.loaderInfo.url.toString();
      
      // remove everything before the question mark, including the question mark
      var regexQuery:RegExp = /.*\?/;
      var queryString:String = url.replace( regexQuery, "" );
      
      // create an array of name=value pairs
      var paramArray:Array = queryString.split( "&" );
      
      // put the names value into an object
      var paramObject:Object;
      var param:String;
      var pair:Array;
      for each( param in paramArray )
      {
         pair = param.split( "=" );
         // name = value
         paramObject[ pair[0] ] = pair[1]; 
      }
      
      return paramObject;
   }

Module and Parent Application Communication

Modules can access properties and methods of the parent application by using the parentApplication property.

Loader applications access properties and methods of Modules by loading them and creating an instance (which has already been explained above).

Module to Module Communication

Modules can also communicate with other Modules loaded by the same application.

You can access properties and methods of other modules through the parent application using a ModuleLoader's child property. This property points to an instance of the module's class, which lets you call methods and access properties.

Consider the following example where a parent application loads two modules, Module1 and Module2.

<!-- Loader (parent) application... -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
   <mx:ModuleLoader url="Module1.swf" id="module1"/>
   <mx:ModuleLoader url="Module2.swf" id="module2"/>
</mx:Application>

Inside of module1 you could call a method or access a property as below.

   // inside of Module1
   parentApplication.module2.child.someProperty;
   parentApplication.module2.child.someMethod();

Benefits of Modules

Modular applications provide the following benefits:

  • Applications can have a smaller initial download size and shorter load times
  • Application modules can be loaded in pieces as they are used
  • Applications can be better encapsulated and pieces worked on independently

Modules vs. Runtime Shared Libraries (RSL)

Both Runtime Shared Libraries (RSL) and Modules are code separation and reuse mechanisms. They share some similarities and have some differences.

Compilation:

  • Modules are compiled into SWF (.swf) files
  • Libraries are compiled into SWC (.swc) files

Usage:

  • Modules are loaded (and can be unloaded) at run-time
  • Libraries are used at compile time and compiled into an application

Application Size:

  • Modules do not contribute to the initial size or load time of an application
  • Libraries used by an application increase its compilation size

Loading Modules accross Domains

To load a Module from one server into an application served from a different server, you must first establish a trust between the module and the application that loads it.

Loading modules accross domains requires use of a Cross Domain Policy file (crossdomain.xml).

Step 1: Loader Application Initialization

In the preinitialize event handler of the loading application call the allowDomain() method, specifying the target domain from which to load a module.

Also load the cross-domain file of the remote server using loadPolicyFile() and by issuing a URLRequest.

   // (Loader) Application initialization
   public function initApp():void
   {
      Security.allowDomain( "remoteservername" );
      
      Security.loadPolicyFile( "http://remoteservername/crossdomain.xml" );
      
      var request:URLRequest = 
         new URLRequest( "http://remoteservername/crossdomain.xml" );
      var loader:URLLoader = new URLLoader();
      loader.load( request );
   }

Step 2: Server Cross Domain Policy

In the cross-domain file of the remote server where your module is, add an entry that specifies the server on which the loading application is running.

   <!-- crossdomain.xml file located at the root of the server -->
   <cross-domain-policy>
      <allow-access-from domain="loaderservername" to-ports="*"/>
   </cross-domain-policy>

Step 3: Module Initialization

In the loaded module, call the allowDomain() method so that it can communicate with the loader.

   // (Remote) Module initialization
   public function initModule():void
   {
      Security.allowDomain( "loaderservername" );
   }

Examples

Monitoring Module Loading with a Progress Bar

TODO...

   ...

Related Links

Related Docs
  • Flash Cross Domain Policy A cross-domain policy file is an XML document that grants Flash Player permission to handle data across multiple domains.
Recent Docs
  • Flex Modules Flex Modules are compiled to dynamically-loadable SWF files that can be loaded and unloaded at run-time.
  • Flex Progress Bar The Flex Progress Bar control is used for displaying progress to users.
  • ActionScript Language Introduction to the ActionScript 3.0 programming language.
  • ActionScript Exceptions ActionScript handles Exceptions using try, catch, and finally.
Random Docs
  • Flex Collection Sorting Sorting Collections with the Sort and SortField objects.
  • Flex Text Controls Flex Text Controls allow the display and input of simple and rich HTML text.
  • Object-Oriented ActionScript ActionScript is a full-featured Object-Oriented language with support for classes, interfaces, encapsulation, polymorphism, and inheritance.
  • Flex Libraries A Library is collection of Flex/ActionScript classes and resources compiled to a .swc file.
  • MXML Namespaces Overview of MXML Namespaces and how to use custom components in MXML.