| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <!DOCTYPE html |
| PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html lang="en-us" xml:lang="en-us"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
| <meta name="DC.Type" content="topic"/> |
| <meta name="DC.Title" content="Modular applications"/> |
| <meta name="DC.Format" content="XHTML"/> |
| <meta name="DC.Identifier" content="WS2db454920e96a9e51e63e3d11c0bf69084-7f22_verapache"/> |
| <link rel="stylesheet" type="text/css" href="commonltr.css"/> |
| <title>Modular applications</title> |
| </head> |
| <body id="WS2db454920e96a9e51e63e3d11c0bf69084-7f22_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7f22_verapache"><!-- --></a> |
| |
| |
| <h1 class="topictitle1">Modular applications</h1> |
| |
| |
| <div> |
| <p/> |
| |
| </div> |
| |
| <div class="nested1" id="WS19f279b149e7481c-3e29f2ba12dbeecdd8a-8000_verapache"><a name="WS19f279b149e7481c-3e29f2ba12dbeecdd8a-8000_verapache"><!-- --></a> |
| <h2 class="topictitle2">Modules quick start</h2> |
| |
| |
| <div> |
| <p>Modules are SWF files that are similar to applications. |
| You use modules to externalize functionality and load it only when |
| it is needed. Applications can load and unload modules at run time, |
| which can save start up time and memory because the applications |
| can be smaller and download faster.</p> |
| |
| <p>The most common use of modules is in a navigator container. Typically, |
| each view in a navigator container is a module. When the user navigates |
| to a new view, a new module is loaded.</p> |
| |
| <p>You compile modules just as you would any application file. On |
| the command line, you create a new module and compile it with the |
| mxmlc compiler. </p> |
| |
| <p>Modules are MXML documents with <samp class="codeph"><s:Module></samp> as |
| the root tag. Within that tag, you can use any child tags that you |
| can use in a <samp class="codeph"><s:Application></samp> tag. The following |
| examples shows two modules:</p> |
| |
| <div class="p">HorizontalLayoutModule.mxml:<pre class="noswf"><?xml version="1.0" encoding="utf-8"?> |
| <!-- modules/mxmlmodules/HorizontalLayoutModule.mxml --> |
| <s:Module xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| minWidth="955" minHeight="600" |
| > |
| <fx:Declarations> |
| </fx:Declarations> |
| <fx:Style> |
| </fx:Style> |
| |
| <fx:Script> |
| <![CDATA[ |
| ]]> |
| </fx:Script> |
| <s:layout> |
| <s:HorizontalLayout /> |
| </s:layout> |
| <s:Label text="label three"/> |
| <s:Button label="button three"/> |
| <s:Label text="label four"/> |
| <s:Button label="button four"/> |
| </s:Module></pre> |
| |
| </div> |
| |
| <div class="p">VerticalLayoutModule.mxml:<pre class="noswf"><?xml version="1.0" encoding="utf-8"?> |
| <!-- modules/mxmlmodules/VerticalLayoutModule.mxml --> |
| <s:Module xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| minWidth="955" minHeight="600"> |
| <fx:Declarations> |
| </fx:Declarations> |
| <fx:Style> |
| </fx:Style> |
| |
| <fx:Script> |
| <![CDATA[ |
| ]]> |
| </fx:Script> |
| <s:layout> |
| <s:VerticalLayout /> |
| </s:layout> |
| <s:Label text="label one"/> |
| <s:TextInput /> |
| <s:Label text="label two"/> |
| <s:TextArea/> |
| </s:Module></pre> |
| |
| </div> |
| |
| <div class="p">To load modules in an application, you use a <samp class="codeph"><s:ModuleLoader></samp> tag |
| inside a container. The container can be an MX container (such as |
| a TabNavigator container), or a Spark container (such as a Group). |
| The following example application uses a TabNavigator container: <pre class="noswf"><?xml version="1.0" encoding="utf-8"?> |
| <!-- modules/SimpleLoader.mxml --> |
| <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| minWidth="955" minHeight="600"> |
| |
| <mx:TabNavigator width="500" height="300"> |
| <s:ModuleLoader label="Tab One" url="mxmlmodules/VerticalLayoutModule.swf"/> |
| <s:ModuleLoader label="Tab Two" url="mxmlmodules/HorizontalLayoutModule.swf"/> |
| </mx:TabNavigator> |
| </s:Application></pre> |
| |
| </div> |
| |
| <p>When the application first loads, Flash Player loads the first |
| module in the first view of the container. When the user navigates |
| to the second view of the container, Flash Player loads the second |
| module.</p> |
| |
| <p>The Spark ModuleLoader class implements the INavigatorContent |
| interface. As a result, it provides some convenience properties |
| for working with navigator containers. For example, you can use |
| the <samp class="codeph">label</samp> property to set a label on the tab in |
| a TabNavigator container, or you can use the <samp class="codeph">icon</samp> property |
| to instead add an icon to the tab.</p> |
| |
| <p>The ModuleLoader class also provides a <samp class="codeph">creationPolicy</samp> property. |
| You can use this property to instruct the application when to load |
| the module. </p> |
| |
| </div> |
| |
| <div><div class="relinfo"><strong>Related information</strong><br/> |
| <div><a href="flx_compilers_cpl.html#WS2db454920e96a9e51e63e3d11c0bf69084-7fcc_verapache">Using mxmlc, the application compiler</a></div> |
| <div><a href="flx_layoutperformance_lp.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cb8_verapache">About the creationPolicy property</a></div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-799a_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-799a_verapache"><!-- --></a> |
| <h2 class="topictitle2">Modular applications overview</h2> |
| |
| |
| <div/> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fff_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fff_verapache"><!-- --></a> |
| <h3 class="topictitle3">About modules</h3> |
| |
| |
| <div> |
| <p> |
| <em>Modules</em> are SWF files that can be loaded and unloaded |
| by an application. They cannot be run independently of an application, |
| but any number of applications can share the modules.</p> |
| |
| <p>Modules let you split your application into several pieces, or |
| modules. The main application, or shell, 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. When the application no |
| longer needs a module, it can unload the module to free up memory and |
| resources. </p> |
| |
| <p>Modular applications have the following benefits:</p> |
| |
| <ul> |
| <li> |
| <p>Smaller initial download size of the SWF file.</p> |
| |
| </li> |
| |
| <li> |
| <p>Less memory use of overall application when modules are unloaded.</p> |
| |
| </li> |
| |
| <li> |
| <p>Shorter load time due to smaller SWF file size.</p> |
| |
| </li> |
| |
| <li> |
| <p>Better encapsulation of related aspects of an application. |
| For example, a “reporting” feature can be separated into a module |
| that you can then work on independently.</p> |
| |
| </li> |
| |
| </ul> |
| |
| <p>Modules and sub-applications are similar in many ways. Before |
| deciding on an architecture for your applications, see the comparison |
| of these two approaches in <a href="flx_loading_applications_la.html#WS2db454920e96a9e51e63e3d11c0bf69084-7f07_verapache">Comparing |
| loaded applications to modules</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff2_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff2_verapache"><!-- --></a> |
| <h3 class="topictitle3">Benefits of modules</h3> |
| |
| |
| <div> |
| <p>A module is a special type of dynamically loadable SWF |
| file that contains an IFlexModuleFactory class factory. This allows |
| an application to load code at run time and create class instances |
| without requiring that the class implementations be linked into |
| the main application. </p> |
| |
| <p>Modules are similar to Runtime Shared Libraries (RSLs) in that |
| they separate code from an application into separately loaded SWF |
| files. Modules are very flexible because modules can be loaded and |
| unloaded at run time and compiled without the application.</p> |
| |
| <p>Two common scenarios in which using modules is beneficial are |
| a large application with different user paths and a portal application.</p> |
| |
| <p>An example of the first common scenario is an enormous insurance |
| application that includes thousands of screens, for life insurance, |
| car insurance, health insurance, dental insurance, travel insurance, |
| and veterinary pet insurance. </p> |
| |
| <p>By using a traditional approach to Rich Internet Application |
| (RIA) design, you might build a monolithic application with a hierarchical |
| tree of MXML classes. Memory use and start-up time for the application |
| would be significant, and the SWF file size would grow with each |
| new set of functionality. </p> |
| |
| <p>When using this application, however, any user accesses only |
| a subset of the screens. By refactoring the screens into small groups |
| of modules that are loaded on demand, you can improve the perceived |
| performance of the main application and reduce the memory use. Also, |
| when the application is separated into modules, developers’ productivity |
| may increase due to better encapsulation of design. When rebuilding |
| the application, the developers also have to recompile only the |
| single module instead of the entire application. </p> |
| |
| <p>An example of the second common scenario is a system with a main |
| portal application, written in ActionScript 3.0, that provides services |
| for numerous portlets. Portlets are configured based on data that |
| is downloaded on a per-user basis. By using the traditional approach, |
| you might build an application that compiles in all known portlets. |
| This is inefficient, both for deployment and development.</p> |
| |
| <p>By using modules, you can establish an interface that contains |
| portal services, and a generic portlet interface. You can use XML |
| data to determine which modules to load for a given session. When |
| the module is loaded, you obtain a handle to a class factory inside |
| the module, and from that you create an instance of a class that |
| implements the portlet interface. In this scenario, full recompilation |
| is necessary only if the interfaces change.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fec_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fec_verapache"><!-- --></a> |
| <h3 class="topictitle3">Module API details</h3> |
| |
| |
| <div> |
| <p>Modules implement a class factory with a standard interface. |
| The product of that class factory implements an interface known |
| to the shell, or the shell implements an interface known to the |
| modules. These shared interfaces reduce hard dependencies between |
| the shell and the module. This provides type-safe communication |
| and enforces an abstraction layer without adding significantly to |
| the SWF file size.</p> |
| |
| <p>The following image shows the relationship between the shell |
| and the module’s interfaces:</p> |
| |
| <div class="figborder"> |
| <img src="images/md_ModuleDiagram.png" alt="The relationship between the shell and the module\xd5 s interface."/> |
| </div> |
| |
| <p>The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleManager.html" target="_blank">ModuleManager</a> manages |
| the set of loaded modules, which are treated as a map of Singletons |
| that are indexed by the module URL. Loading a module triggers a |
| series of events that let clients monitor the status of the module. Modules |
| are only ever loaded once, but subsequent reloads also dispatch |
| events so that client code can be simplified and rely on using the <samp class="codeph">READY</samp> event |
| to know that the module’s class factory is available for use.</p> |
| |
| <p>The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/ModuleLoader.html" target="_blank">ModuleLoader</a> class |
| is a thin layer on top of the ModuleManager API that is intended |
| to act similarly to the mx.controls.SWFLoader class for modules |
| that only define a single visual UIComponent. The ModuleLoader class |
| is the easiest class to use when implementing a module-based architecture, |
| but the ModuleManager provides greater control over the modules.</p> |
| |
| <p>The ModuleLoader class implements the INavigatorContent interface |
| so that it can be used directly by MX-based navigator containers |
| (such as TabNavigator). The ModuleLoader class does not have any |
| UI associated with it. All UI is defined by the module that it loads.</p> |
| |
| <p>The Spark Module class extends the SkinnableContainer class. |
| This means you can skin it and add visual components, including |
| graphics, as children.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d0f_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d0f_verapache"><!-- --></a> |
| <h3 class="topictitle3">Module domains and sharing class |
| libraries</h3> |
| |
| |
| <div> |
| <p>By default, a module is loaded into a child domain of the |
| current application domain. You can specify a different application |
| domain by using the <samp class="codeph">applicationDomain</samp> property |
| of the ModuleLoader class. </p> |
| |
| <p>Because a module is loaded into a child domain, it owns class |
| definitions that are not in the main application’s domain. For example, |
| the first module to load the PopUpManager class becomes the owner |
| of the PopUpManager class for the entire application because it |
| registers the manager with the SingletonManager. If another module |
| later tries to use the PopUpManager, Adobe <sup>®</sup> Flash<sup>®</sup> Player throws an exception. </p> |
| |
| <p>One solution is to use framework RSLs when compiling your applications |
| and modules (RSLs are enabled by default). The definitions of the |
| manager classes will be loaded in the framework RSL by the main |
| application. Then, all the modules and sub-applications can share |
| it. For more information about using framework RSLs with modules, |
| see <a href="flx_modular_md.html#WS19f279b149e7481c-7592484b12db94a3ab2-8000_verapache">Using |
| RSLs with modules</a>.</p> |
| |
| <p>If you do not use RSLs, the solution is to ensure that managers |
| such as PopUpManager and DragManager and any other shared services |
| are defined by the main application (or loaded late into the shell’s |
| application domain). When you promote one of those classes to the |
| main application, the class can then be used by all modules. Typically, |
| this is done by adding the following to a script block in the main |
| application:</p> |
| |
| <pre class="codeblock"> import mx.managers.PopUpManager; |
| import mx.managers.DragManager; |
| import mx.managers.ToolTipManager; |
| import mx.managers.CursorManager; |
| import mx.core.EmbeddedFontRegistry; |
| |
| private var popUpManager:PopUpManager; |
| private var dragManager:DragManager; |
| private var tooltipManager:ToolTipManager; |
| private var cursorManager:CursorManager; |
| private var embeddedFontRegistry:EmbeddedFontRegistry;</pre> |
| |
| <p>You should only define these classes in your main application |
| if your modules use the related functionality. For example, define |
| the EmbeddedFontRegistry class in your main application if one or |
| more of your modules uses embedded fonts.</p> |
| |
| <p>This technique also applies to components. The module that first |
| uses the component owns that component’s class definition in its |
| domain. As a result, if another module tries to use a component |
| that has already been used by another module, its definition will |
| not match the existing definition. </p> |
| |
| <p>To avoid a mismatch of component definitions, create an instance |
| of the component in the main application. The result is that the |
| definition of the component is owned by the main application and |
| can be used by modules in any child domain.</p> |
| |
| <p>By default, modules do not share the main application’s StyleManager, |
| however. They have their own instances of the IStyleManager2 class. |
| As a result, modules can define their own styles. For example, style |
| properties set on a Button control in one module are not applied |
| to the Button control in another module or to the main application.</p> |
| |
| <p>Because a module must be in the same security domain as the application |
| (SWF) that loads it, when you’re using modules in an AIR application, |
| any module SWF must be located in the same directory as the main |
| application SWF or one of its subdirectories, which ensures that, |
| like the main application SWF, the module SWF is in the AIR application |
| security sandbox. One way to verify this is to ensure that a relative |
| URL for the module’s location doesn’t require "../" ("up one level") notation |
| to navigate outside the application directory or one of its subdirectories.</p> |
| |
| <p>For more information about application domains, see <a href="flx_loading_applications_la.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d14_verapache">Developing |
| and loading sub-applications</a>.</p> |
| |
| </div> |
| |
| <div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff4_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff4_verapache"><!-- --></a> |
| <h4 class="topictitle4">Create a modular application</h4> |
| |
| |
| <div> |
| <p>To create a modular application, you create separate classes |
| for each module, and an application that loads the modules. </p> |
| |
| <ol> |
| <li> |
| <p>Create any number of modules. An MXML-based module file’s |
| root tag is <samp class="codeph"><s:Module></samp>. ActionScript-based |
| modules extend either the Module or ModuleBase class.</p> |
| |
| </li> |
| |
| <li> |
| <p>Compile each module as if it were an application. You can |
| do this by using the mxmlc command-line compiler.</p> |
| |
| </li> |
| |
| <li> |
| <p>Create an Application class. This is typically an MXML file |
| whose root tag is <samp class="codeph"><s:Application></samp>, but it |
| can also be an ActionScript-only application.</p> |
| |
| </li> |
| |
| <li> |
| <p>In the Application file, use an <samp class="codeph"><s:ModuleLoader></samp> tag |
| to load each of the modules. You can also load modules by using |
| methods of the spark.modules.ModuleLoader and mx.modules.ModuleManager |
| classes in ActionScript.</p> |
| |
| </li> |
| |
| </ol> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WSda78ed3a750d6b8f1b97f82d12508050aa0-8000_verapache"><a name="WSda78ed3a750d6b8f1b97f82d12508050aa0-8000_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using styles with modules</h3> |
| |
| |
| <div> |
| <p>When you set styles on modules, the style properties are |
| set on the local StyleManager. Each module has its own instance |
| of the IStyleManager2 class. This means that each module can load |
| its own set of styles, and its styles do not necessarily affect |
| the styles of other modules.</p> |
| |
| <p>After an application finishes loading a module, the module’s |
| styles are merged with the styles of the application. The module’s |
| StyleManager walks the chain of parent modules and applications, |
| up to the top-level StyleManager, and merges its styles with those |
| set on the StyleManagers above it.</p> |
| |
| <p>If during a style merge, a module encounters a style that it |
| already sets on itself, the style is ignored. If the module encounters |
| a style not set on itself, the style is added to the merged style |
| definition. The styles set on the StyleManager that is closest to |
| the module wins. </p> |
| |
| <div class="p">The following example loads two modules. The main application |
| sets the <samp class="codeph">color</samp> and <samp class="codeph">cornerRadius</samp> style |
| properties on the Button control type selector. The modules each |
| set the <samp class="codeph">color</samp> property on the Button control type |
| selector. The merged styles result in the Buttons having a corner |
| radius of 10, with colors set by each module. This shows how style |
| merges work.<pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/StyleModLoaderApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Style> |
| @namespace s "library://ns.adobe.com/flex/spark"; |
| |
| s|Button { |
| color:blue; |
| cornerRadius:10; |
| } |
| </fx:Style> |
| |
| <s:VGroup> |
| <s:Label id="l1" text="Module 1"/> |
| <s:ModuleLoader id="ml1" url="mxmlmodules/StyleMod1.swf"/> |
| </s:VGroup> |
| |
| <s:VGroup> |
| <s:Label id="l2" text="Module 2"/> |
| <s:ModuleLoader id="ml2" url="mxmlmodules/StyleMod2.swf"/> |
| </s:VGroup> |
| |
| <s:Button id="myButton" label="Main App Button"/> |
| |
| </s:Application></pre> |
| |
| </div> |
| |
| <div class="p">Module 1:<pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/mxmlmodules/StyleMod1.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <fx:Style> |
| @namespace s "library://ns.adobe.com/flex/spark"; |
| |
| s|Button { |
| color:red; |
| } |
| </fx:Style> |
| |
| <s:Button label="StyleMod1"/> |
| |
| </s:Module></pre> |
| |
| </div> |
| |
| <div class="p">Module 2:<pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/mxmlmodules/StyleMod2.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <fx:Style> |
| @namespace s "library://ns.adobe.com/flex/spark"; |
| |
| s|Button { |
| color:green; |
| } |
| </fx:Style> |
| |
| <s:Button label="StyleMod2"/> |
| |
| </s:Module></pre> |
| |
| </div> |
| |
| <p>To prevent style merges, set the <samp class="codeph">isolate-styles</samp> compiler |
| argument to <samp class="codeph">false</samp>. By doing this, you might trigger |
| type coercion errors when loading skins. Modules also might not |
| be properly garbage collected when they are unloaded. This is because |
| the main application’s StyleManager will maintain references to the |
| module even after is is unloaded. When you set <samp class="codeph">isolate-styes</samp> to <samp class="codeph">false</samp>, if |
| more than one module loads a style, the first one loaded wins. In |
| this case, styles set on modules can be overridden by those set |
| on other modules.</p> |
| |
| <p>In the previous example, if you set the <samp class="codeph">isolate-styles</samp> compiler |
| argument to <samp class="codeph">false</samp>, the color of the Button controls’ |
| labels in both modules would be red, because that is definition |
| that is first loaded.</p> |
| |
| <p>The <samp class="codeph">getStyleDeclarations()</samp> method returns only |
| the local style definitions. To get the merged style definitions, |
| you can use the <samp class="codeph">getMergedStyleDeclaration()</samp> method. |
| All methods that modify style definitions affect only the local |
| style definitions and not the merged style definitions.</p> |
| |
| <p>Style properties are merged when the module is loaded. This means |
| that style properties set on the main application and all child |
| applications and modules are set on the module if the module does |
| not override that style. Merged styles are set on a per-property |
| basis, starting with the closest StyleManager and working upwards |
| to the top-level StyleManager.</p> |
| |
| <div class="p">Even when using merged styles, child modules still inherit their |
| parent module or application’s inheritable style properties when |
| those settings are applied at runtime. Their StyleManager is not |
| changed, but the values of the properties are inherited and applied |
| where applicable. If you set a property at run time on the main |
| application, the modules inherit that style immediately, as the |
| following example shows:<pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/StyleModLoaderApp2.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| /* When you set this style in the main application, the modules immediately |
| inherit the value. */ |
| private function changeStyle():void { |
| styleManager.getStyleDeclaration("spark.components.Button").setStyle("fontSize", 15); |
| } |
| </fx:Script> |
| |
| <fx:Style> |
| @namespace s "library://ns.adobe.com/flex/spark"; |
| |
| s|Button { |
| color:blue; |
| cornerRadius:10; |
| } |
| </fx:Style> |
| |
| <s:VGroup> |
| <s:Label id="l1" text="Module 1"/> |
| <s:ModuleLoader id="ml1" url="mxmlmodules/StyleMod1.swf"/> |
| </s:VGroup> |
| |
| <s:VGroup> |
| <s:Label id="l2" text="Module 2"/> |
| <s:ModuleLoader id="ml2" url="mxmlmodules/StyleMod2.swf"/> |
| </s:VGroup> |
| |
| <s:Button label="Change Styles" click="changeStyle()"/> |
| |
| </s:Application></pre> |
| |
| </div> |
| |
| <p>For information on using run-time style sheets with modules, |
| see <a href="flx_styles_st.html#WS2db454920e96a9e51e63e3d11c0bf69084-7e6d_verapache">Using |
| run-time style sheets with modules and sub-applications</a>.</p> |
| |
| <p>If you use run-time resource bundles with loaded modules, you |
| should consider setting the <samp class="codeph">addResourceBundle()</samp> method’s <samp class="codeph">useWeakReferences</samp> parameter |
| to <samp class="codeph">true</samp>. For more information, see <a href="flx_resourcebundles_rb.html#WS19f279b149e7481c-6f660f0612ca9140b8f-8000_verapache">Preventing |
| memory leaks in modules and sub-applications</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS19f279b149e7481c-7592484b12db94a3ab2-8000_verapache"><a name="WS19f279b149e7481c-7592484b12db94a3ab2-8000_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using RSLs with modules</h3> |
| |
| |
| <div> |
| <p>Starting with Flex 4.5, modules work much more efficiently |
| with RSLs. Modules will not load RSLs that the main application |
| has already loaded, and modules can share RSLs with other modules.</p> |
| |
| <p>The application only loads those framework RSLs that are needed |
| at startup, and creates placeholders for all remaining framework |
| RSLs. When a module is loaded, it does not try to load RSLs that |
| are already loaded by the main application. If the module needs |
| a framework RSL that is not initially loaded by the main application |
| (and has a placeholder), then the module loads the RSL.</p> |
| |
| <p>In addition, when a module loads an RSL, you can specify which |
| domain the RSL is loaded into with the <samp class="codeph">application-domain</samp> compiler |
| argument. This lets you load an RSL into the parent, current, or |
| top-level application domains. This applies to both framework RSLs |
| and custom RLSs. </p> |
| |
| <p>For more information about using modules and RSLs, see <a href="flx_rsl_rsl.html#WS19f279b149e7481c311d007d12d9f3bc5d8-8000_verapache">Using |
| RSLs with modules and sub-applications</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS19f279b149e7481c-5c393e7912dc8e2afe8-8000_verapache"><a name="WS19f279b149e7481c-5c393e7912dc8e2afe8-8000_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using pop-ups with modules</h3> |
| |
| |
| <div> |
| <p>When using modules as pop-ups, you might not be able to |
| click or drag the pop-up. The solution is to create a subclass of |
| the pop-up (such as a TitleWindow container) that you use as the |
| top-level MXML tag in the Module.</p> |
| |
| <p>For more information, see <a href="http://blogs.adobe.com/aharui/2007/08/popup_dialogs_as_modules.html" target="_blank">Alex's Flex Closet</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7997_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7997_verapache"><!-- --></a> |
| <h2 class="topictitle2">Writing modules</h2> |
| |
| |
| <div> |
| <p>Modules are classes just like application files. You can |
| create them either in ActionScript or by extending a Flex class |
| by using MXML tags. You can create modules in MXML and in ActionScript. </p> |
| |
| <p>After you compile a module, you can load it into an application |
| or another module. Typically, you use one of the following techniques |
| to load MXML-based modules:</p> |
| |
| <ul> |
| <li> |
| <p>ModuleLoader — The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/ModuleLoader.html" target="_blank">ModuleLoader</a> class |
| provides the highest-level API for handling modules. For more information, |
| see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d21_verapache">Using |
| the ModuleLoader class to load modules</a>.</p> |
| |
| </li> |
| |
| <li> |
| <p>ModuleManager — The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleManager.html" target="_blank">ModuleManager</a> class |
| provides a lower-level API for handling modules than the ModuleLoader |
| class does. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d20_verapache">Using |
| the ModuleManager class to load modules</a>.</p> |
| |
| </li> |
| |
| </ul> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fe3_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fe3_verapache"><!-- --></a> |
| <h3 class="topictitle3">Creating MXML-based modules</h3> |
| |
| |
| <div> |
| <p>To create a module in MXML, you extend the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/Module.html" target="_blank">spark.modules.Module </a>class |
| by creating a file whose root tag is <samp class="codeph"><s:Module></samp>. |
| In that tag, ensure that you add any namespaces that are used in |
| that module. You must also include an XML type declaration tag at |
| the beginning of the file, such as the following:</p> |
| |
| <pre class="codeblock"> <?xml version="1.0"?></pre> |
| |
| <p>The following example is a module that includes a Chart control:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ColumnChartModule.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%" > |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script><![CDATA[ |
| import mx.collections.ArrayCollection; |
| [Bindable] |
| public var expenses:ArrayCollection = new ArrayCollection([ |
| {Month:"Jan", Profit:2000, Expenses:1500}, |
| {Month:"Feb", Profit:1000, Expenses:200}, |
| {Month:"Mar", Profit:1500, Expenses:500} |
| ]); |
| ]]></fx:Script> |
| |
| <mx:ColumnChart id="myChart" dataProvider="{expenses}"> |
| <mx:horizontalAxis> |
| <mx:CategoryAxis |
| dataProvider="{expenses}" |
| categoryField="Month"/> |
| </mx:horizontalAxis> |
| <mx:series> |
| <mx:ColumnSeries |
| xField="Month" |
| yField="Profit" |
| displayName="Profit"/> |
| <mx:ColumnSeries |
| xField="Month" |
| yField="Expenses" |
| displayName="Expenses"/> |
| </mx:series> |
| </mx:ColumnChart> |
| <mx:Legend dataProvider="{myChart}"/> |
| </s:Module></pre> |
| |
| <p>After you create a module, you compile it as if it were an application. |
| For more information on compiling modules, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1f_verapache">Compiling |
| modules</a>. </p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d1e_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d1e_verapache"><!-- --></a> |
| <h3 class="topictitle3">Creating ActionScript-based modules</h3> |
| |
| |
| <div> |
| <p>To create a module in ActionScript, you can create a file |
| that extends either the spark.modules.Module class or the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleBase.html" target="_blank">mx.modules.ModuleBase </a>class. </p> |
| |
| <p>Extending the Module class is the same as using the <samp class="codeph"><s:Module></samp> tag |
| in an MXML file. You should extend this class if your module interacts |
| with the framework; this typically means that it adds objects to |
| the display list or otherwise interacts with visible objects.</p> |
| |
| <p>To see an example of an ActionScript class that extends the Module |
| class, create an MXML file with the root tag of <samp class="codeph"><s:Module></samp>. |
| When you compile this file, set the value of the <samp class="codeph">keep-generated-actionscript</samp> compiler |
| property to <samp class="codeph">true</samp>. The Flex compiler stores the |
| generated ActionScript class in a directory called generated. You |
| will notice that this generated class contains code that you probably |
| will not understand. As a result, you should not write ActionScript-based |
| modules that extend the Module class; instead, you should use MXML |
| to write such modules.</p> |
| |
| <p>If your module does not include any framework code, you can create |
| a class that extends ModuleBase. If you use the ModuleBase class, |
| your module will typically be smaller than if you use a module based |
| on the Module class because it does not have any framework class |
| dependencies.</p> |
| |
| <p>The following example creates a simple module that does not contain |
| any framework code and therefore extends the ModuleBase class: </p> |
| |
| <pre class="noswf">// modules/asmodules/SimpleModule.as |
| package { |
| import mx.modules.ModuleBase; |
| |
| public class SimpleModule extends ModuleBase { |
| public function SimpleModule() { |
| trace("SimpleModule created"); |
| } |
| |
| public function computeAnswer(a:Number, b:Number):Number { |
| return a + b; |
| } |
| } |
| }</pre> |
| |
| <p>To call the <samp class="codeph">computeAnswer()</samp> method on the ActionScript |
| module, you can use one of the techniques shown in <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1a_verapache">Accessing |
| modules from the parent application</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d1f_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d1f_verapache"><!-- --></a> |
| <h2 class="topictitle2">Compiling modules</h2> |
| |
| |
| <div> |
| <p>The way you compile modules is similar to the way you compile |
| applications. On the command line, you use the mxmlc command-line |
| compiler; for example:</p> |
| |
| <pre class="codeblock"> mxmlc MyModule.mxml </pre> |
| |
| <p>The result of compiling a module is a SWF file that you load |
| into your application. You cannot run the module-based SWF file |
| as a stand-alone application or load it into a browser window. It |
| must be loaded by an application as a module. Modules should not |
| be opened directly by Adobe<sup>®</sup> Flash<sup>®</sup> Player or Adobe<sup>®</sup> AIR,™ or requested through a browser directly.</p> |
| |
| <p>When you compile your module, you should try to remove redundancies between |
| the module and the application that uses it. To do this on the command line, |
| you create a link report for the application, and then externalize |
| any assets in the module that appear in that report. For more information, |
| see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d15_verapache">Reducing module |
| size</a>.</p> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d15_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d15_verapache"><!-- --></a> |
| <h3 class="topictitle3">Reducing module size</h3> |
| |
| |
| <div> |
| <p>Module size varies based on the components and classes |
| that are used in the module. By default, a module externalizes all |
| framework code that its components depend on by using RSLs. However, |
| other custom classes and libraries are not externalized by default, |
| which can cause modules to be larger than necessary by linking classes |
| that overlap with the application’s classes.</p> |
| |
| <p>To reduce the size of the modules, you can optimize the module |
| by instructing the compiler to externalize classes that are included |
| by the application. This includes custom classes and framework classes. |
| The result is that the module includes only the classes it requires, |
| while the framework code and other dependencies are included in |
| the application.</p> |
| |
| <p>If you want to use a module with more than one application, you |
| might want to optimize it for no applications so that it contains |
| all the class references necessary to run, regardless of the parent |
| application.</p> |
| |
| </div> |
| |
| <div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ffa_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ffa_verapache"><!-- --></a> |
| <h4 class="topictitle4">Create and use a linker report |
| with the command-line compiler</h4> |
| |
| |
| <div> |
| <p>To externalize framework classes with the command-line |
| compiler, you generate a linker report from the application that |
| loads the modules. You then use this report as input to the module’s <samp class="codeph">load-externs</samp> compiler |
| option. The compiler externalizes all classes from the module for |
| which the application contains definitions. </p> |
| |
| <ol> |
| <li> |
| <p>Generate the linker report and compile the application:</p> |
| |
| <pre class="codeblock"> mxmlc -link-report=report.xml MyApplication.mxml</pre> |
| |
| <p>The |
| default output location of the linker report is the same directory |
| as the compiler. In this case, it would be in the bin directory.</p> |
| |
| </li> |
| |
| <li> |
| <p>Compile the module and pass the linker report to the <samp class="codeph">load-externs</samp> option:</p> |
| |
| <pre class="codeblock"> mxmlc -load-externs=report.xml MyModule.mxml</pre> |
| |
| </li> |
| |
| </ol> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fe5_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fe5_verapache"><!-- --></a> |
| <h3 class="topictitle3">Recompiling modules</h3> |
| |
| |
| <div> |
| <p>If you change a module, you do not have to recompile the |
| application that uses the module if that module is in the same project. |
| This is because the application loads the module at run time and |
| does not check against it at compile time. Similarly, if you make |
| changes to the application, you do not have to recompile the module. |
| Just as the application does not check against the module at compile |
| time, the module does not check against the application until run |
| time.</p> |
| |
| <p>If the module is in a separate project than the application that |
| loads it, you must recompile the module separately.</p> |
| |
| <p>However, if you make changes that might affect the linker report |
| or common code, you should recompile both the application and the |
| modules.</p> |
| |
| <div class="note"><span class="notetitle">Note:</span> If you externalize the module’s dependencies |
| by using the <samp class="codeph">load-externs</samp> or <samp class="codeph"> |
| <em>optimize</em> |
| </samp> option, |
| your module might not be compatible with future versions of Adobe |
| Flex. You might be required to recompile the module. To ensure that |
| a future application can use a module, compile that module with |
| all the classes it requires. This also applies to applications that |
| you load inside other applications.</div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fee_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fee_verapache"><!-- --></a> |
| <h3 class="topictitle3">Debugging modules </h3> |
| |
| |
| <div> |
| <p>To debug an application that uses modules, you set the <samp class="codeph">debug</samp> compiler |
| option to <samp class="codeph">true</samp> for the modules when you compile |
| them. Otherwise, you will not be able to set breakpoints in the |
| modules or gather other debugging information from them. On the |
| command line, debugging is disabled by default. You must also set |
| the <samp class="codeph">debug</samp> option to <samp class="codeph">true</samp> when |
| you compile the application that loads the modules that you want |
| to debug.</p> |
| |
| <p>A common issue that occurs when using multiple modules is that |
| modules sometimes own the class definitions that the other modules |
| want to use. Because they are in sibling application domains, the |
| module that loaded the class definition first owns the definition |
| for that class, but other modules will experience errors when they |
| try to use that class. The solution is to promote the class definition |
| to the main application domain so that all modules can use the class. |
| For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d0f_verapache">Module |
| domains and sharing class libraries</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ffd_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ffd_verapache"><!-- --></a> |
| <h2 class="topictitle2">Loading and unloading modules</h2> |
| |
| |
| <div> |
| <p>There are several techniques you can use to load and unload |
| modules in your applications. These techniques include:</p> |
| |
| <ul> |
| <li> |
| <p>ModuleLoader — The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/ModuleLoader.html" target="_blank">ModuleLoader</a> class |
| provides the highest-level API for handling modules. For more information, |
| see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d21_verapache">Using |
| the ModuleLoader class to load modules</a>.</p> |
| |
| </li> |
| |
| <li> |
| <p>ModuleManager — The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleManager.html" target="_blank">ModuleManager</a> class |
| provides a lower-level API for handling modules than the ModuleLoader |
| class does. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d20_verapache">Using |
| the ModuleManager class to load modules</a>.</p> |
| |
| </li> |
| |
| </ul> |
| |
| <p>When you’re using modules in an AIR application, the module SWF |
| file must be located in the same directory as the main application |
| SWF file or one of its subdirectories.</p> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d21_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d21_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using the ModuleLoader class to |
| load modules</h3> |
| |
| |
| <div> |
| <p>You can use the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/ModuleLoader.html" target="_blank">ModuleLoader </a>class |
| to load a module in an application or other module. The easiest |
| way to do this in an MXML application is to use the <samp class="codeph"><s:ModuleLoader></samp> tag. |
| You set the value of the <samp class="codeph">url</samp> property to point |
| to the location of the module’s SWF file. The following example |
| loads the module when the application first starts:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/MySimplestModuleLoader.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:ModuleLoader url="ColumnChartModule.swf"/> |
| |
| </s:Application></pre> |
| |
| <p>You can change the timing of when the module loads by setting |
| the value of the <samp class="codeph">url</samp> property at some other time, |
| such as in response to an event. Setting the target URL of a ModuleLoader |
| object triggers a call to the <samp class="codeph">loadModule()</samp> method. |
| This occurs when you first create a ModuleLoader object with the <samp class="codeph">url</samp> property |
| set. It also occurs if you change the value of that property. </p> |
| |
| <p>If you set the value of the <samp class="codeph">url</samp> property to |
| an empty string (<samp class="codeph">""</samp>) or <samp class="codeph">null</samp>, |
| the ModuleLoader object unloads the current module by calling the <samp class="codeph">release()</samp> method.</p> |
| |
| <p>You can have multiple instances of the ModuleLoader class in |
| a single application. The following example loads the modules when |
| the user navigates to the appropriate tabs in the TabNavigator container:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/URLModuleLoaderApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:Panel title="Module Example" width="100%" height="100%"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <mx:TabNavigator id="tn" |
| paddingTop="10" |
| paddingLeft="10" |
| paddingRight="10" |
| paddingBottom="10" |
| width="100%" height="100%" |
| creationPolicy="auto"> |
| <s:ModuleLoader id="ml1" |
| label="ColumnChart Module" |
| url="ColumnChartModule.swf"/> |
| <s:ModuleLoader id="ml2" |
| label="BarChart Module" |
| url="BarChartModule.swf"/> |
| </mx:TabNavigator> |
| </s:Panel> |
| </s:Application></pre> |
| |
| <p>You can also use the ModuleLoader API to load and unload modules |
| with the <samp class="codeph">loadModule()</samp> and <samp class="codeph">unloadModule()</samp> methods. |
| These methods take no parameters; the ModuleLoader class loads or |
| unloads the module that matches the value of the current <samp class="codeph">url</samp> property.</p> |
| |
| <p>The following example loads and unloads the module when you click |
| the button:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ASModuleLoaderApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import spark.modules.ModuleLoader; |
| |
| public function createModule(m:ModuleLoader, s:String):void { |
| if (!m.url) { |
| m.url = s; |
| } |
| m.loadModule(); |
| } |
| |
| public function removeModule(m:ModuleLoader):void { |
| m.unloadModule(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Panel title="Module Example" width="100%" height="100%"> |
| <mx:TabNavigator id="tn" |
| paddingTop="10" |
| paddingLeft="10" |
| paddingRight="10" |
| paddingBottom="10" |
| width="100%" height="100%" |
| creationPolicy="auto"> |
| <s:NavigatorContent label="ColumnChartModule"> |
| <s:layout> |
| <s:VerticalLayout paddingTop="10" paddingLeft="5"/> |
| </s:layout> |
| <s:Button label="Load" |
| click="createModule(chartModuleLoader, l1.text)"/> |
| <s:Button label="Unload" |
| click="removeModule(chartModuleLoader)"/> |
| <s:Label id="l1" text="ColumnChartModule.swf"/> |
| <s:ModuleLoader id="chartModuleLoader"/> |
| </s:NavigatorContent> |
| |
| <s:NavigatorContent label="FormModule"> |
| <s:layout> |
| <s:VerticalLayout paddingTop="10" paddingLeft="5"/> |
| </s:layout> |
| <s:Button label="Load" |
| click="createModule(formModuleLoader, l2.text)"/> |
| <s:Button label="Unload" |
| click="removeModule(formModuleLoader)"/> |
| <s:Label id="l2" text="FormModule.swf"/> |
| <s:ModuleLoader id="formModuleLoader"/> |
| </s:NavigatorContent> |
| </mx:TabNavigator> |
| </s:Panel> |
| </s:Application></pre> |
| |
| <p>When you load a module, Flex ensures that there is only one copy |
| of a module loaded, no matter how many times you call the <samp class="codeph">load()</samp> method |
| for that module. </p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d20_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d20_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using the ModuleManager class to |
| load modules</h3> |
| |
| |
| <div> |
| <p>You can use the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleManager.html" target="_blank">ModuleManager </a>class |
| to load the module. This technique is less abstract than using the <samp class="codeph"><s:ModuleLoader></samp> tag, |
| but it does provide you with greater control over how and when the |
| module is loaded. </p> |
| |
| <div class="p">To use the ModuleManager to load a module in ActionScript:<ol> |
| <li> |
| <p>Get a reference to the module’s <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/IModuleInfo.html" target="_blank">IModuleInfo</a> interface |
| by using the ModuleManager <samp class="codeph">getModule()</samp> method.</p> |
| |
| </li> |
| |
| <li> |
| <p>Call the interface’s <samp class="codeph">load()</samp> method. </p> |
| |
| <div class="p">The |
| application that loads the module should pass in its <samp class="codeph">moduleFactory</samp> property. |
| This lets the module know who its parent style manager is. When using |
| the <samp class="codeph">load()</samp> method, you can specify the application’s <samp class="codeph">moduleFactory</samp> with |
| the fourth parameter, as the following example shows:<pre class="codeblock">info.load(null, null, null, moduleFactory);</pre> |
| |
| </div> |
| |
| </li> |
| |
| <li> |
| <p>Use the <samp class="codeph">factory</samp> property of the interface |
| to call the <samp class="codeph">create()</samp> method and cast the return |
| value as the module’s class. If you are adding the module to a container, |
| you can cast the return value as an IVisualElement (for Spark containers) |
| or a DisplayObject (for MX containers) so that they can be added to |
| the display list.</p> |
| |
| </li> |
| |
| </ol> |
| |
| </div> |
| |
| <p>The following example shell application loads the ColumnChartModule.swf |
| file. The example then adds the modules to the display list so that |
| it appears when the application starts:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ModuleLoaderApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| creationComplete="initApp()"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.events.ModuleEvent; |
| import mx.modules.ModuleManager; |
| import mx.modules.IModuleInfo; |
| import mx.core.IVisualElement; |
| |
| public var info:IModuleInfo; |
| |
| private function initApp():void { |
| info = ModuleManager.getModule("ColumnChartModule.swf"); |
| info.addEventListener(ModuleEvent.READY, modEventHandler); |
| /* Load the module into memory. Calling load() makes the |
| IFlexModuleFactory available. You can then get an |
| instance of the class using the factory's create() |
| method. */ |
| info.load(null, null, null, moduleFactory); |
| } |
| |
| /* Add an instance of the module's class to the display list. */ |
| private function modEventHandler(e:ModuleEvent):void { |
| /* For MX containers, cast to a DisplayObject. */ |
| vb1.addChild(info.factory.create() as DisplayObject); |
| |
| /* For Spark containers, cast to a UIComponent. */ |
| vg1.addElement(info.factory.create() as IVisualElement); |
| } |
| ]]> |
| </fx:Script> |
| |
| <!-- MX container --> |
| <mx:VBox id="vb1"> |
| <s:Label text="Module loaded in MX VBox container:"/> |
| </mx:VBox> |
| |
| <!-- Spark container --> |
| <s:VGroup id="vg1"> |
| <s:Label text="Module loaded in Spark VGroup container:"/> |
| </s:VGroup> |
| |
| </s:Application></pre> |
| |
| <p>The <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/IModuleInfo.html" target="_blank">IModuleInfo</a> class’s <samp class="codeph">load()</samp> method |
| also optionally takes an ApplicationDomain and a SecurityDomain |
| as arguments. If you do not specify either of these (or set them |
| to <samp class="codeph">null</samp>), then the module is loaded into a new |
| child domain.</p> |
| |
| <p>MXML-based modules can load other modules. Those modules can |
| load other modules, and so on.</p> |
| |
| <p>Be sure to define the module instance outside of a function, |
| so that it is not in the function’s local scope. Otherwise, the |
| object might be garbage collected and the associated event listeners |
| might never be invoked.</p> |
| |
| <p>If you remove all references to the module, it will be garbage |
| collected. You do not need to call the <samp class="codeph">unload()</samp> method |
| when adding and removing modules using the IModuleInfo class. You |
| just need to set the IModuleInfo instance to <samp class="codeph">null</samp>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff0_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff0_verapache"><!-- --></a> |
| <h3 class="topictitle3">Loading modules from different |
| servers</h3> |
| |
| |
| <div> |
| <p>To load a module from one server into an application running |
| on a different server, you must establish trust between the module |
| and the application that loads it. </p> |
| |
| </div> |
| |
| <div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fef_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fef_verapache"><!-- --></a> |
| <h4 class="topictitle4">Access applications across domains</h4> |
| |
| |
| <div> |
| <ol> |
| <li> |
| <p>In your loading application, you must call the <samp class="codeph">allowDomain()</samp> method |
| and specify the target domain from which you load a module. So, |
| specify the target domain in the preinitialize event handler of |
| your application to ensure that the application is set up before |
| the module is loaded. </p> |
| |
| </li> |
| |
| <li> |
| <p>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.</p> |
| |
| </li> |
| |
| <li> |
| <p>Load the cross-domain file on the remote server in the preinitialize |
| event handler of your loading application. </p> |
| |
| </li> |
| |
| <li> |
| <p>In the loaded module, call the <samp class="codeph">allowDomain()</samp> method |
| so that it can communicate with the loader. </p> |
| |
| </li> |
| |
| </ol> |
| |
| <p>The following example shows the <samp class="codeph">init()</samp> method |
| of the loading application:</p> |
| |
| <pre class="codeblock"> public function setup():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); |
| }</pre> |
| |
| <p>The following example shows the loaded module’s <samp class="codeph">init()</samp> method:</p> |
| |
| <pre class="codeblock"> public function initMod():void { |
| Security.allowDomain("loaderservername"); |
| }</pre> |
| |
| <p>The following example shows the cross-domain file that resides |
| on the remote server:</p> |
| |
| <pre class="codeblock"> <!-- crossdomain.xml file located at the root of the server --> |
| <cross-domain-policy> |
| <site-control permitted-cross-domain-policies="all"/> |
| <allow-access-from domain="loaderservername" to-ports="*"/> |
| </cross-domain-policy></pre> |
| |
| <p>For more information about using the cross-domain policy file, |
| see <a href="flx_security2_se.html#WS2db454920e96a9e51e63e3d11c0bf69084-7f9b_verapache">Security</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7feb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7feb_verapache"><!-- --></a> |
| <h3 class="topictitle3">Preloading modules</h3> |
| |
| |
| <div> |
| <p>When you first start an application that uses modules, |
| the application’s file size should be smaller than a similar application |
| that does not use modules. As a result, there should be a reduction |
| in wait time because the application can be loaded into memory and |
| run before the modules’ SWF files are even transferred across the |
| network. However, there will be a delay when the user navigates |
| to a part in the application that uses the module. This is because |
| the modules are not by default preloaded, but rather loaded when |
| they are first requested.</p> |
| |
| <p>When a module is loaded by the application for the first time, |
| the module’s SWF file is transferred across the network and stored |
| in the browser’s cache. If the application unloads that module, |
| but then later reloads it, there should be less wait time because |
| Flash Player loads the module from the cache rather than across |
| the network.</p> |
| |
| <p>Module SWF files, like all SWF files, reside in the browser’s |
| cache unless and until a user clears them. As a result, modules |
| can be loaded by the main application across several sessions, reducing |
| load time; but this depends on how frequently the browser’s cache |
| is flushed.</p> |
| |
| <p>You can preload modules at any time so that you can have the |
| modules’ SWF files in memory even if the module is not currently |
| being used.</p> |
| |
| <p>To preload modules on application startup, use the IModuleInfo |
| class <samp class="codeph">load()</samp> method. This loads the module into |
| memory but does not create an instance of the module. </p> |
| |
| <p>The following example loads the BarChartModule.swf module when |
| the application starts up, even though it will not be displayed |
| until the user navigates to the second pane of the TabNavigator |
| container. Without preloading, the user would wait for the SWF file |
| to be transferred across the network when they navigated to the |
| second pane of the TabNavigator.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/PreloadModulesApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| creationComplete="preloadModules()"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.events.ModuleEvent; |
| import mx.modules.ModuleManager; |
| import mx.modules.IModuleInfo; |
| |
| private function preloadModules():void { |
| /* Get a reference to the module's interface. */ |
| var info:IModuleInfo = |
| ModuleManager.getModule("BarChartModule.swf"); |
| info.addEventListener(ModuleEvent.READY, modEventHandler); |
| |
| /* Load the module into memory. The module will be |
| displayed when the user navigates to the second |
| tab of the TabNavigator. */ |
| info.load(); |
| } |
| |
| private function modEventHandler(e:ModuleEvent):void { |
| trace("module event: " + e.type); // "ready" |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Panel title="Module Example" width="100%" height="100%"> |
| <mx:TabNavigator id="tn" |
| paddingTop="10" |
| paddingLeft="10" |
| paddingRight="10" |
| paddingBottom="10" |
| width="100%" height="100%" |
| creationPolicy="auto"> |
| <s:ModuleLoader label="ColumnChartModule" |
| url="ColumnChartModule.swf"/> |
| <s:ModuleLoader label="BarChartModule" |
| url="BarChartModule.swf"/> |
| </mx:TabNavigator> |
| </s:Panel> |
| </s:Application></pre> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff8_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff8_verapache"><!-- --></a> |
| <h2 class="topictitle2">Using ModuleLoader events</h2> |
| |
| |
| <div> |
| <p>The ModuleLoader class triggers several events, including <samp class="codeph">setup</samp>, <samp class="codeph">ready</samp>, <samp class="codeph">loading</samp>, <samp class="codeph">unload</samp>, <samp class="codeph">progress</samp>, <samp class="codeph">error</samp>, |
| and <samp class="codeph">urlChanged</samp>. You can use these events to track |
| the loading process, and find out when a module has been unloaded |
| or when the ModuleLoader target URL has changed.</p> |
| |
| <p>The following example uses a custom ModuleLoader component. This component |
| reports all the events of the modules as they are loaded by the |
| main application.</p> |
| |
| <p>Custom ModuleLoader:</p> |
| |
| <pre class="noswf"><?xml version="1.0" encoding="iso-8859-1"?> |
| <!-- modules/CustomModuleLoader.mxml --> |
| <s:ModuleLoader |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| xmlns="*" |
| creationComplete="init()"> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.core.UIComponent; |
| |
| public var standin:UIComponent; |
| |
| public function init():void { |
| addEventListener("urlChanged", onUrlChanged); |
| addEventListener("loading", onLoading); |
| addEventListener("progress", onProgress); |
| addEventListener("setup", onSetup); |
| addEventListener("ready", onReady); |
| addEventListener("error", onError); |
| addEventListener("unload", onUnload); |
| |
| standin = panel; |
| removeElement(standin); |
| } |
| |
| public function onUrlChanged(event:Event):void { |
| if (url == null) { |
| if (contains(standin)) |
| removeElement(standin); |
| } else { |
| if (!contains(standin)) |
| addElement(standin); |
| } |
| progress.indeterminate=true; |
| unload.enabled=false; |
| reload.enabled=false; |
| } |
| |
| public function onLoading(event:Event):void { |
| progress.label="Loading module " + url; |
| if (!contains(standin)) |
| addElement(standin); |
| |
| progress.indeterminate=true; |
| unload.enabled=false; |
| reload.enabled=false; |
| } |
| |
| public function onProgress(event:Event):void { |
| progress.label="Loaded %1 of %2 bytes..."; |
| progress.indeterminate=false; |
| unload.enabled=true; |
| reload.enabled=false; |
| } |
| |
| public function onSetup(event:Event):void { |
| progress.label="Module " + url + " initialized!"; |
| progress.indeterminate=false; |
| unload.enabled=true; |
| reload.enabled=true; |
| } |
| |
| public function onReady(event:Event):void { |
| progress.label="Module " + url + " successfully loaded!"; |
| unload.enabled=true; |
| reload.enabled=true; |
| |
| if (contains(standin)) |
| removeElement(standin); |
| } |
| |
| public function onError(event:Event):void { |
| progress.label="Error loading module " + url; |
| unload.enabled=false; |
| reload.enabled=true; |
| } |
| |
| public function onUnload(event:Event):void { |
| if (url == null) { |
| if (contains(standin)) |
| removeElement(standin); |
| } else { |
| if (!contains(standin)) |
| addElement(standin); |
| } |
| progress.indeterminate=true; |
| progress.label="Module " + url + " was unloaded!"; |
| unload.enabled=false; |
| reload.enabled=true; |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Panel id="panel" width="100%" title="Status &amp; Operations"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| <mx:ProgressBar width="100%" id="progress" source="{this}"/> |
| <s:HGroup width="100%"> |
| <s:Button id="unload" label="Unload Module" click="unloadModule()"/> |
| <s:Button id="reload" label="Reload Module" click="unloadModule();loadModule()"/> |
| </s:HGroup> |
| </s:Panel> |
| </s:ModuleLoader></pre> |
| |
| <p>Main application:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/EventApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| xmlns="*"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| [Bindable] |
| public var selectedModule:Object; |
| ]]> |
| </fx:Script> |
| |
| <s:ComboBox width="215" labelField="label" prompt="Select Coverage" |
| close="selectedModule=ComboBox(event.target).selectedItem"> |
| <s:dataProvider> |
| <s:ArrayCollection> |
| <fx:Object label="Life Insurance" |
| module="insurancemodules/LifeInsurance.swf"/> |
| <fx:Object label="Auto Insurance" |
| module="insurancemodules/AutoInsurance.swf"/> |
| <fx:Object label="Home Insurance" |
| module="insurancemodules/HomeInsurance.swf"/> |
| </s:ArrayCollection> |
| </s:dataProvider> |
| </s:ComboBox> |
| |
| <s:Panel width="100%" height="100%" title="Custom Module Loader"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| <CustomModuleLoader id="mod" width="100%" url="{selectedModule.module}"/> |
| </s:Panel> |
| <s:HGroup> |
| <s:Button label="Unload" click="mod.unloadModule()"/> |
| <s:Button label="Nullify" click="mod.url=null"/> |
| </s:HGroup> |
| </s:Application></pre> |
| |
| <p>The insurance modules used in this example are simple forms, |
| such as the following:</p> |
| |
| <pre class="noswf"><?xml version="1.0" encoding="utf-8"?> |
| <!-- modules/insurancemodules/AutoInsurance.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| backgroundColor="#ffffff" |
| width="100%" height="100%"> |
| <s:Label x="147" y="50" text="Auto Insurance" |
| fontSize="28" fontFamily="Myriad Pro"/> |
| <s:Form left="47" top="80"> |
| <s:FormHeading label="Coverage"/> |
| <s:FormItem label="Latte Spillage"> |
| <s:TextInput id="latte" width="200"/> |
| </s:FormItem> |
| <s:FormItem label="Shopping Cart to the Door"> |
| <s:TextInput id="cart" width="200"/> |
| </s:FormItem> |
| <s:FormItem label="Irate Moose"> |
| <s:TextInput id="moose" width="200"/> |
| </s:FormItem> |
| <s:FormItem label="Color Fade"> |
| <mx:ColorPicker/> |
| </s:FormItem> |
| </s:Form> |
| </s:Module></pre> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff7_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff7_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using the error event</h3> |
| |
| |
| <div> |
| <p>The <samp class="codeph">error</samp> event gives you an opportunity |
| to gracefully fail when a module does not load for some reason. |
| In the following example, you can load and unload a module by using |
| the Button controls. To trigger an <samp class="codeph">error</samp> event, |
| change the URL in the TextInput control to a module that does not |
| exist. The error handler displays a message to the user and writes |
| the error message to the trace log.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ErrorEventHandler.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout |
| paddingTop="10" |
| paddingLeft="10" |
| paddingRight="10" |
| paddingBottom="10"/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.events.ModuleEvent; |
| import spark.modules.ModuleLoader; |
| import spark.modules.Module; |
| import mx.controls.Alert; |
| |
| private function errorHandler(e:ModuleEvent):void { |
| Alert.show("There was an error loading the module." + |
| " Please contact the Help Desk.\n" + |
| e.errorText); |
| } |
| |
| public function createModule():void { |
| if (chartModuleLoader.url == ti1.text) { |
| /* If they are the same, call the loadModule() method. */ |
| chartModuleLoader.loadModule(); |
| } else { |
| /* If they are not the same, then change the url, |
| which then triggers a call to the loadModule() method. */ |
| chartModuleLoader.url = ti1.text; |
| } |
| } |
| |
| public function removeModule():void { |
| chartModuleLoader.unloadModule(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Panel title="Module Example" height="90%" width="90%"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| <s:HGroup> |
| <s:Label text="URL:"/> |
| <s:TextInput width="200" id="ti1" text="ColumnChartModule.swf"/> |
| <s:Button label="Load" click="createModule()"/> |
| <s:Button label="Unload" click="removeModule()"/> |
| </s:HGroup> |
| <s:ModuleLoader id="chartModuleLoader" error="errorHandler(event)"/> |
| </s:Panel> |
| </s:Application></pre> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64277-7ff6_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7ff6_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using the progress event</h3> |
| |
| |
| <div> |
| <p>You can use the <samp class="codeph">progress</samp> event to track |
| the progress of a module as it loads. When you add a listener for |
| the <samp class="codeph">progress</samp> event, Flex calls that listener at regular |
| intervals during the module’s loading process. Each time the listener |
| is called, you can look at the <samp class="codeph">bytesLoaded</samp> property |
| of the event. You can compare this to the <samp class="codeph">bytesTotal</samp> property |
| to get a percentage of completion.</p> |
| |
| <p>The following example reports the level of completion during |
| the module’s loading process. It also produces a simple progress |
| bar that shows users how close the loading is to being complete.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/SimpleProgressEventHandler.mxml --> |
| <s:Application |
| creationComplete="initApp()" |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.events.ModuleEvent; |
| import flash.events.ProgressEvent; |
| import spark.modules.Module; |
| import spark.modules.ModuleLoader; |
| |
| [Bindable] |
| public var progBar:String = ""; |
| [Bindable] |
| public var progMessage:String = ""; |
| |
| private function progressEventHandler(e:ProgressEvent):void { |
| progBar += "."; |
| progMessage = |
| "Module " + |
| Math.round((e.bytesLoaded/e.bytesTotal) * 100) + |
| "% loaded"; |
| } |
| |
| public function initApp():void { |
| chartModuleLoader.url = "ColumnChartModule.swf"; |
| } |
| |
| public function createModule():void { |
| chartModuleLoader.loadModule(); |
| } |
| |
| public function removeModule():void { |
| chartModuleLoader.unloadModule(); |
| progBar = ""; |
| progMessage = ""; |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Panel title="Module Example" height="90%" width="90%"> |
| <s:layout> |
| <s:VerticalLayout |
| paddingTop="10" paddingLeft="10" |
| paddingRight="10" paddingBottom="10"/> |
| </s:layout> |
| |
| <s:HGroup> |
| <s:Label id="l2" text="{progMessage}"/> |
| <s:Label id="l1" text="{progBar}"/> |
| </s:HGroup> |
| <s:Button label="Load" click="createModule()"/> |
| <s:Button label="Unload" click="removeModule()"/> |
| |
| <s:ModuleLoader id="chartModuleLoader" |
| progress="progressEventHandler(event)"/> |
| </s:Panel> |
| </s:Application></pre> |
| |
| <p>You can also connect a module loader to a ProgressBar control. |
| The following example creates a custom component for the ModuleLoader |
| that includes a ProgressBar control. The ProgressBar control displays |
| the progress of the module loading.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/MySimpleModuleLoader.mxml --> |
| <s:ModuleLoader |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| private function clickHandler():void { |
| if (!url) { |
| url="ColumnChartModule.swf"; |
| } |
| loadModule(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <mx:ProgressBar id="progress" width="100%" source="{this}"/> |
| <s:HGroup width="100%"> |
| <s:Button id="load" label="Load" click="clickHandler()"/> |
| <s:Button id="unload" label="Unload" click="unloadModule()"/> |
| <s:Button id="reload" label="Reload" click="unloadModule();loadModule();"/> |
| </s:HGroup> |
| </s:ModuleLoader></pre> |
| |
| <p>You can use this module in a simple application, as the following |
| example shows:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ComplexProgressEventHandler.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| xmlns:local="*"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <s:Panel title="Module Example" height="90%" width="90%"> |
| <s:layout> |
| <s:VerticalLayout |
| paddingTop="10" paddingLeft="10" |
| paddingRight="10" paddingBottom="10"/> |
| </s:layout> |
| <s:Label text="Use the buttons below to load and unload the module."/> |
| <local:MySimpleModuleLoader id="customLoader"/> |
| </s:Panel> |
| |
| </s:Application></pre> |
| |
| <p>This example does not change the ProgressBar <samp class="codeph">label</samp> property |
| for all events. For example, if you load and then unload the module, |
| the <samp class="codeph">label</samp> property remains at "LOADING 100%". To |
| adjust the label properly, you must define other event handlers |
| for the ModuleLoader events, such as <samp class="codeph">unload</samp> and <samp class="codeph">error</samp>. </p> |
| |
| </div> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf64277-7fea_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64277-7fea_verapache"><!-- --></a> |
| <h2 class="topictitle2">Passing data to modules</h2> |
| |
| |
| <div> |
| <p>Communication between modules and the parent application, |
| and among modules, is possible. You can use the following approaches |
| to facilitate inter-module, application-to-module, and module-to-application |
| communication:</p> |
| |
| <ul> |
| <li> |
| <p>Interfaces — You can create ActionScript interfaces that |
| define the methods and properties that modules and applications |
| can access. This gives you greater control over module and application |
| interaction. It also prevents you from creating dependencies between |
| modules and applications. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache">Using |
| interfaces for module communication</a>.</p> |
| |
| </li> |
| |
| <li> |
| <p>Query string parameters — Modules are loaded with a URL; |
| you can pass parameters on this URL and then parse those parameters |
| in the module. This is only a way to pass simple data, and is not |
| appropriate for complex data. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d10_verapache">Passing |
| data to modules with the query string</a>.</p> |
| |
| </li> |
| |
| <li> |
| <p> |
| <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/modules/ModuleLoader.html" target="_blank">ModuleLoader</a> |
| <samp class="codeph">’s child</samp>, <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/modules/ModuleManager.html" target="_blank">ModuleManager</a> ‘s<samp class="codeph"> factory</samp>, |
| and Application’s <samp class="codeph">parentApplication</samp> properties |
| — You can use these properties to access modules and applications. |
| However, by using these properties, you create a tightly-coupled |
| design that prevents code reuse and is easily broken. In addition, |
| you also create dependencies among modules and applications that cause |
| class sizes to be bigger. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1a_verapache">Accessing |
| modules from the parent application</a>, <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1b_verapache">Accessing |
| the parent application from modules</a>, and <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d22_verapache">Accessing |
| modules from other modules</a>.</p> |
| |
| </li> |
| |
| </ul> |
| |
| <p>The following techniques for accessing methods and properties |
| apply to parent applications as well as modules. Modules can load |
| other modules, which makes the loading module similar to the parent |
| application in the simpler examples.</p> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache"><!-- --></a> |
| <h3 class="topictitle3">Using interfaces for module communication</h3> |
| |
| |
| <div> |
| <p>You can use an interface to provide module-to-application |
| communication. Your modules implement the interface and your application |
| calls its methods or sets its properties. The interface defines |
| stubs for the methods and properties that you want the application |
| and module to share. The module implements an interface known to |
| the application, or the application implements an interface known |
| to the module. This lets you avoid so-called hard dependencies between the |
| module and the application.</p> |
| |
| <p>In the main application, when you want to call methods on the |
| module, you cast the ModuleLoader class’s <samp class="codeph">child</samp> property |
| to an instance of the custom interface.</p> |
| |
| <p>The following example application lets you customize the appearance |
| of the module that it loads by calling methods on the custom IModuleInterface interface. |
| The application also calls the <samp class="codeph">getModuleName()</samp> method. |
| This method returns a value from the module and sets a local property |
| to that value.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/interfaceexample/MainModuleApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| xmlns="*"> |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.events.ModuleEvent; |
| import mx.modules.ModuleManager; |
| |
| [Bindable] |
| public var selectedItem:Object; |
| |
| [Bindable] |
| public var currentModuleName:String; |
| |
| private function applyModuleSettings(e:Event):void { |
| /* Cast the ModuleLoader's child to the interface. |
| This child is an instance of the module. |
| You can now call methods on that instance. */ |
| var ichild:* = mod.child as IModuleInterface; |
| if (mod.child != null) { |
| /* Call setters in the module to adjust its |
| appearance when it loads. */ |
| ichild.setAdjusterID(myId.text); |
| ichild.setBackgroundColor(myColor.selectedColor); |
| } else { |
| trace("Uh oh. The mod.child property is null"); |
| } |
| /* Set the value of a local variable by calling a method |
| on the interface. */ |
| currentModuleName = ichild.getModuleName(); |
| } |
| |
| private function reloadModule():void { |
| // Reset the ColorPicker control: |
| myColor.selectedColor = 0xFFFFFF; |
| |
| // Reload the module: |
| mod.unloadModule(); |
| mod.loadModule(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Form> |
| <s:FormItem label="Current Module:"> |
| <s:Label id="l1" text="{currentModuleName}"/> |
| </s:FormItem> |
| <s:FormItem label="Adjuster ID:"> |
| <s:TextInput id="myId" text="Enter your ID"/> |
| </s:FormItem> |
| <s:FormItem label="Background Color:"> |
| <mx:ColorPicker id="myColor" |
| selectedColor="0xFFFFFF" |
| change="applyModuleSettings(event)"/> |
| </s:FormItem> |
| </s:Form> |
| |
| <s:Label text="Long Shot Insurance" fontSize="24"/> |
| <s:ComboBox labelField="label" prompt="Select Module" |
| close="selectedItem=ComboBox(event.target).selectedItem"> |
| <s:dataProvider> |
| <s:ArrayList> |
| <fx:Object label="Auto Insurance" module="AutoInsurance2.swf"/> |
| </s:ArrayList> |
| </s:dataProvider> |
| </s:ComboBox> |
| |
| <s:Panel width="100%" height="100%"> |
| <s:ModuleLoader id="mod" |
| width="80%" height="80%" |
| url="{selectedItem.module}" |
| ready="applyModuleSettings(event)"/> |
| </s:Panel> |
| <s:Button id="b1" label="Reload Module" click="reloadModule()"/> |
| </s:Application></pre> |
| |
| <p>The following example defines a simple interface that has two |
| getters and one setter. This interface is used by the application |
| in the previous example.</p> |
| |
| <pre class="codeblock">// modules/interfaceexample/IModuleInterface.as |
| package |
| { |
| import flash.events.IEventDispatcher; |
| |
| public interface IModuleInterface extends IEventDispatcher { |
| |
| function getModuleName():String; |
| function setAdjusterID(s:String):void; |
| function setBackgroundColor(n:Number):void; |
| } |
| |
| }</pre> |
| |
| <p>The following example defines the module that is loaded by the |
| previous example. It implements the custom IModuleInterface interface.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/interfaceexample/AutoInsurance2.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%" implements="IModuleInterface"> |
| |
| <s:Panel id="p1" title="Auto Insurance" |
| width="100%" height="100%" |
| backgroundColor="{bgcolor}"> |
| <s:Label id="myLabel" text="ID: {adjuster}"/> |
| </s:Panel> |
| |
| <fx:Script> |
| <![CDATA[ |
| [Bindable] |
| private var adjuster:String; |
| [Bindable] |
| private var bgcolor:Number; |
| |
| public function setAdjusterID(s:String):void { |
| adjuster = s; |
| } |
| |
| public function setBackgroundColor(n:Number):void { |
| /* Use a bindable property to set values of controls |
| in the module. This ensures that the property will be set |
| even if Flex applies the property after the module is |
| loaded but before it is rendered by the player. */ |
| bgcolor = n; |
| |
| /* Don't do this. The backgroundColor style might not be set |
| by the time the ModuleLoader triggers the READY |
| event: */ |
| // p1.setStyle("backgroundColor", n); |
| } |
| |
| public function getModuleName():String { |
| return "Auto Insurance"; |
| } |
| ]]> |
| </fx:Script> |
| </s:Module></pre> |
| |
| <p>In general, if you want to set properties on controls in the |
| module by using external values, you should create variables that |
| are bindable. You then set the values of those variables in the |
| interface’s implemented methods. If you try to set properties of |
| the module’s controls directly by using external values, the controls might |
| not be instantiated by the time the module is loaded and the attempt |
| to set the properties might fail. </p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d10_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d10_verapache"><!-- --></a> |
| <h3 class="topictitle3">Passing data to modules with the |
| query string</h3> |
| |
| |
| <div> |
| <p>One way to pass data to a module is to append query string |
| parameters to the URL that you use to load the module. You can then |
| parse the query string by using ActionScript to access the data. </p> |
| |
| <p>In the module, you can access the URL by using the <samp class="codeph">loaderInfo</samp> property. |
| This property points to the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/LoaderInfo.html" target="_blank">LoaderInfo </a>object |
| of the loading SWF (in this case, the main application). The information |
| provided by the LoaderInfo object includes load progress, the URLs |
| of the loader and loaded content, the file size of the application, |
| and the height and width of the application.</p> |
| |
| <p>The following example application builds a unique query string |
| for the module that it loads. The query string includes a <samp class="codeph">firstName</samp> and <samp class="codeph">lastName</samp> parameter.</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/QueryStringApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| height="500" width="400"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| public function initModule():void { |
| // Build query string so that it looks something like this: |
| // "QueryStringModule.swf?firstName=Nick&lastName=Danger" |
| var s:String = "QueryStringModule.swf?" + "firstName=" + |
| ti1.text + "&lastName=" + ti2.text; |
| |
| // Changing the url property of the ModuleLoader causes |
| // the ModuleLoader to load a new module. |
| m1.url = s; |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Form> |
| <s:FormItem id="fi1" label="First Name:"> |
| <s:TextInput id="ti1"/> |
| </s:FormItem> |
| <s:FormItem id="fi2" label="Last Name:"> |
| <s:TextInput id="ti2"/> |
| </s:FormItem> |
| </s:Form> |
| |
| <s:ModuleLoader id="m1"/> |
| |
| <s:Button id="b1" label="Submit" click="initModule()"/> |
| |
| </s:Application></pre> |
| |
| <p>The following example module parses the query string that was |
| used to load it. If the <samp class="codeph">firstName</samp> and <samp class="codeph">lastName</samp> parameters |
| are set, the module prints the results in a TextArea. The module |
| also traces some additional information available through the LoaderInfo |
| object:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/QueryStringModule.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| creationComplete="parseString()"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.utils.*; |
| |
| [Bindable] |
| private var salutation:String; |
| |
| public var o:Object = {}; |
| |
| public function parseString():void { |
| try { |
| /* Remove everything before the question mark, including |
| the question mark. */ |
| var myPattern:RegExp = /.*\?/; |
| var s:String = this.loaderInfo.url.toString(); |
| s = s.replace(myPattern, ""); |
| |
| /* Create an Array of name=value Strings. */ |
| var params:Array = s.split("&"); |
| |
| /* Print the params that are in the Array. */ |
| var keyStr:String; |
| var valueStr:String; |
| var paramObj:Object = params; |
| for (keyStr in paramObj) { |
| valueStr = String(paramObj[keyStr]); |
| ta1.text += keyStr + ":" + valueStr + "\n"; |
| } |
| |
| /* Set the values of the salutation. */ |
| for (var i:int = 0; i < params.length; i++) { |
| var tempA:Array = params[i].split("="); |
| if (tempA[0] == "firstName") { |
| o.firstName = tempA[1]; |
| } |
| if (tempA[0] == "lastName") { |
| o.lastName = tempA[1]; |
| } |
| } |
| if (StringUtil.trim(o.firstName) != "" && |
| StringUtil.trim(o.lastName) != "") { |
| salutation = "Welcome " + |
| o.firstName + " " + o.lastName + "!"; |
| } else { |
| salutation = "Full name not entered." |
| } |
| } catch (e:Error) { |
| trace(e); |
| } |
| |
| /* Show some of the information available through loaderInfo: */ |
| ta2.text = "AS version: " + this.loaderInfo.actionScriptVersion; |
| ta2.text += "\nApp height: " + this.loaderInfo.height; |
| ta2.text += "\nApp width: " + this.loaderInfo.width; |
| ta2.text += "\nApp bytes: " + this.loaderInfo.bytesTotal; |
| } |
| ]]> |
| </fx:Script> |
| <s:Label text="{salutation}"/> |
| <s:TextArea height="75" width="250" id="ta1"/> |
| <s:TextArea height="200" width="250" id="ta2"/> |
| </s:Module></pre> |
| |
| <p>This example uses methods of the <a href="String.html" target="_blank">String </a>and <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/utils/StringUtil.html" target="_blank">StringUtil </a>classes, |
| plus a for-in loop to parse the URLs. You can also use methods of |
| the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/utils/URLUtil.html" target="_blank">URLUtil </a>and <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLVariables.html" target="_blank">URLVariables </a>classes |
| to do this.</p> |
| |
| <p>Modules are cached by their URL, including the query string. |
| As a result, you will load a new module if you change the URL or |
| any of the query string parameters in the URL. This can be useful |
| if you want multiple instances of a module based on the parameters |
| that you pass in the URL with the ModuleLoader.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d1b_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d1b_verapache"><!-- --></a> |
| <h3 class="topictitle3">Accessing the parent application |
| from modules</h3> |
| |
| |
| <div> |
| <p>Modules can access properties and methods of the parent |
| application by using a reference to the <samp class="codeph">parentApplication</samp> property. |
| In most cases, you should avoid doing this as it creates a close |
| coupling between the module and the application. Having this coupling |
| directly negates some of the benefits of using modules.</p> |
| |
| <p>The following example accesses the <samp class="codeph">expenses</samp> property |
| of the parent application when the module first loads. The module |
| then uses this property, an ArrayCollection, as the source for its |
| chart’s data. When the user clicks the button, the module calls |
| the <samp class="codeph">getNewData()</samp> method of the parent application |
| that returns a new ArrayCollection for the chart:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ChartChildModule.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%" |
| creationComplete="getDataFromParent()"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.collections.ArrayCollection; |
| |
| [Bindable] |
| private var expenses:ArrayCollection; |
| |
| // Access properties of the parent application. |
| private function getDataFromParent():void { |
| expenses = parentApplication.expenses; |
| } |
| ]]> |
| </fx:Script> |
| |
| <mx:ColumnChart id="myChart" dataProvider="{expenses}"> |
| <mx:horizontalAxis> |
| <mx:CategoryAxis dataProvider="{expenses}" categoryField="Month"/> |
| </mx:horizontalAxis> |
| <mx:series> |
| <mx:ColumnSeries xField="Month" yField="Profit" |
| displayName="Profit"/> |
| <mx:ColumnSeries xField="Month" yField="Expenses" |
| displayName="Expenses"/> |
| </mx:series> |
| </mx:ColumnChart> |
| <mx:Legend dataProvider="{myChart}"/> |
| |
| <s:Button id="b1" |
| click="expenses = parentApplication.getNewData();" |
| label="Get New Data"/> |
| |
| </s:Module></pre> |
| |
| <p>The following example shows the parent application that the previous |
| example module uses:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ChartChildModuleLoader.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.collections.ArrayCollection; |
| |
| [Bindable] |
| public var expenses:ArrayCollection = new ArrayCollection([ |
| {Month:"Jan", Profit:2000, Expenses:1500}, |
| {Month:"Feb", Profit:1000, Expenses:200}, |
| {Month:"Mar", Profit:1500, Expenses:500} |
| ]); |
| |
| public function getNewData():ArrayCollection { |
| return new ArrayCollection([ |
| {Month:"Apr", Profit:1000, Expenses:1100}, |
| {Month:"May", Profit:1300, Expenses:500}, |
| {Month:"Jun", Profit:1200, Expenses:600} |
| ]); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:ModuleLoader url="ChartChildModule.swf" id="m1"/> |
| |
| </s:Application></pre> |
| |
| <p>You can also call methods and access properties on other modules. |
| For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d22_verapache">Accessing |
| modules from other modules</a>.</p> |
| |
| <p>The drawback to this approach is that it can create dependencies |
| on the parent application inside the module. In addition, the modules |
| are no longer portable across multiple applications unless you ensure |
| that you replicate the behavior of the applications.</p> |
| |
| <p>To avoid these drawbacks, you should use interfaces that secure |
| a contract between the application and its modules. This contract |
| defines the methods and properties that you can access. Having an |
| interface lets you reuse the application and modules as long as |
| you keep the interface updated. For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache">Using |
| interfaces for module communication</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d22_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d22_verapache"><!-- --></a> |
| <h3 class="topictitle3">Accessing modules from other modules</h3> |
| |
| |
| <div> |
| <p>You can access properties and methods of other modules |
| by using references to the other modules through the parent application. |
| You do this by using the ModuleLoader class’s <samp class="codeph">child</samp> property. |
| This property points to an instance of the module’s class, which |
| lets you call methods and access properties. In most cases, you |
| should avoid doing this as it creates a close coupling among the |
| modules. Having this coupling directly negates some of the benefits |
| of using modules in the first place.</p> |
| |
| <p>The following example defines a single application that loads |
| two modules. The InterModule1 module defines a method that returns |
| a String. The InterModule2 module calls that method and sets the |
| value of its Label to the return value of that method. </p> |
| |
| <p>Main application:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/InterModuleLoader.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| ]]> |
| </fx:Script> |
| |
| <s:ModuleLoader url="InterModule1.swf" id="m1"/> |
| |
| <s:ModuleLoader url="InterModule2.swf" id="m2"/> |
| |
| </s:Application></pre> |
| |
| <p>Module 1:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/InterModule1.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%"> |
| |
| <fx:Script> |
| <![CDATA[ |
| /* Defines the method that the other module calls. */ |
| public function getNewTitle():String { |
| return "New Title"; |
| } |
| ]]> |
| </fx:Script> |
| </s:Module></pre> |
| |
| <p>Module 2:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/InterModule2.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| [Bindable] |
| private var title:String = "Original Title"; |
| |
| // Call method of another module. |
| private function changeTitle():void { |
| title = parentApplication.m1.child.getNewTitle(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:HGroup> |
| <s:Label id="l1" text="Title: "/> |
| <s:Label id="myTitle" text="{title}"/> |
| </s:HGroup> |
| <s:Button id="b1" label="Change Title" click="changeTitle()"/> |
| </s:Module></pre> |
| |
| <p>The application in this example lets the two modules communicate |
| with each other. You could, however, define methods and properties |
| on the application that the modules could access. For more information, |
| see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1b_verapache">Accessing |
| the parent application from modules</a>.</p> |
| |
| <p>As with accessing the parent application’s properties and methods |
| directly, using the technique described in this section can make |
| your modules difficult to reuse and also can create dependencies |
| that can cause the module to be larger than necessary. Instead, |
| you should use interfaces to define the contract between modules. |
| For more information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache">Using |
| interfaces for module communication</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7d1a_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7d1a_verapache"><!-- --></a> |
| <h3 class="topictitle3">Accessing modules from the parent |
| application</h3> |
| |
| |
| <div> |
| <p>You can access the methods and properties of a module from |
| its parent application by getting an instance of the module’s class. |
| Referencing a module by its class name in an application causes |
| the whole module and all of its dependencies to be linked into the |
| application. This defeats the purpose of using modules. However, |
| using this technique can be useful for debugging and testing.</p> |
| |
| <p>You should only use interfaces to access the methods and properties |
| of a module unless you want to create these dependencies. For more |
| information, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1d_verapache">Using interfaces |
| for module communication</a>.</p> |
| |
| <p>If you use the ModuleLoader to load the module, you can call |
| methods on a module from the parent application by referencing the |
| ModuleLoader class’s <samp class="codeph">child</samp> property, and casting |
| it to the module’s class. The <samp class="codeph">child</samp> property is |
| an instance of the module’s class. In this case, the module’s class |
| is the name of the MXML file that defines the module.</p> |
| |
| <p>The following example calls the module’s <samp class="codeph">getTitle()</samp> method |
| from the parent application:</p> |
| |
| <p>Parent Application:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ParentApplication.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script><![CDATA[ |
| [Bindable] |
| private var s:String; |
| |
| private function getTitle():void { |
| s = (m1.child as ChildModule1).getModTitle(); |
| } |
| ]]></fx:Script> |
| |
| <s:Label id="l1" text="{s}"/> |
| <s:ModuleLoader id="m1" |
| url="ChildModule1.swf" |
| ready="getTitle()"/> |
| </s:Application></pre> |
| |
| <p>Module:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/ChildModule1.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| width="100%" height="100%"> |
| <fx:Script><![CDATA[ |
| /* Defines the method that the application calls. */ |
| public function getModTitle():String { |
| return "Child Module 1"; |
| } |
| ]]></fx:Script> |
| </s:Module></pre> |
| |
| <p>If you load the module that you want to call by using the ModuleManager |
| API, there is some additional coding in the shell application. You |
| use the ModuleManager <samp class="codeph">factory</samp> property to get an |
| instance of the module’s class. You can then call the module’s method |
| on that instance.</p> |
| |
| <p>The following module example defines a single method, <samp class="codeph">computeAnswer()</samp>:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/mxmlmodules/SimpleModule.mxml --> |
| <s:Module |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx"> |
| |
| <fx:Script> |
| <![CDATA[ |
| public function computeAnswer(a:Number, b:Number):Number { |
| return a + b; |
| } |
| ]]> |
| </fx:Script> |
| |
| </s:Module></pre> |
| |
| <p>The following example gets an instance of the SimpleModule class |
| by using the <samp class="codeph">factory</samp> property to call the <samp class="codeph">create()</samp> method. |
| It then calls the module’s <samp class="codeph">computeAnswer()</samp> method |
| on that instance:</p> |
| |
| <pre class="noswf"><?xml version="1.0"?> |
| <!-- modules/mxmlmodules/SimpleMXMLApp.mxml --> |
| <s:Application |
| xmlns:fx="http://ns.adobe.com/mxml/2009" |
| xmlns:s="library://ns.adobe.com/flex/spark" |
| xmlns:mx="library://ns.adobe.com/flex/mx" |
| creationComplete="initApp()"> |
| |
| <s:layout> |
| <s:VerticalLayout/> |
| </s:layout> |
| |
| <fx:Script> |
| <![CDATA[ |
| import mx.modules.IModuleInfo; |
| import mx.modules.ModuleManager; |
| |
| public var assetModule:IModuleInfo; |
| public var sm:Object; |
| |
| [Bindable] |
| public var answer:Number = 0; |
| |
| public function initApp():void { |
| /* Get the IModuleInfo interface for the specified URL. */ |
| assetModule = ModuleManager.getModule("SimpleModule.swf"); |
| assetModule.addEventListener("ready", getModuleInstance); |
| assetModule.load(null, null, null, moduleFactory); |
| } |
| |
| public function getModuleInstance(e:Event):void { |
| /* Get an instance of the module. */ |
| sm = assetModule.factory.create() as SimpleModule; |
| } |
| |
| public function addNumbers():void { |
| var a:Number = Number(ti1.text); |
| var b:Number = Number(ti2.text); |
| |
| /* Call a method on the module. */ |
| answer = sm.computeAnswer(a, b).toString(); |
| } |
| ]]> |
| </fx:Script> |
| |
| <s:Form> |
| <s:FormHeading label="Enter values to sum."/> |
| <s:FormItem label="First Number"> |
| <s:TextInput id="ti1" width="50"/> |
| </s:FormItem> |
| <s:FormItem label="Second Number"> |
| <s:TextInput id="ti2" width="50"/> |
| </s:FormItem> |
| <s:FormItem label="Result"> |
| <s:Label id="ti3" width="100" text="{answer}"/> |
| </s:FormItem> |
| <s:Button id="b1" label="Compute" click="addNumbers()"/> |
| </s:Form> |
| </s:Application></pre> |
| |
| <p>In this example, you should actually create a module that extends |
| the ModuleBase class in ActionScript rather than an MXML-based module |
| that extends the Module class. This is because the example module |
| does not have any visual elements and contains only a single method |
| that computes and returns a value. A module that extends the ModuleBase |
| class would be more lightweight than a class that extends Module. |
| For more information on writing ActionScript-based modules that |
| extend the ModuleBase class, see <a href="flx_modular_md.html#WS2db454920e96a9e51e63e3d11c0bf69084-7d1e_verapache">Creating |
| ActionScript-based modules</a>.</p> |
| |
| </div> |
| |
| </div> |
| |
| <p>Adobe, Adobe AIR and Adobe Flash Player are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries and are used by permission from Adobe. No other license to the Adobe trademarks are granted.</p> |
| </div> |
| |
| |
| </body> |
| </html> |