沙漠中的鱼

欲上天堂,先下地狱
posts - 0, comments - 56, trackbacks - 0, articles - 119
  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理

加载和卸载模型

Posted on 2008-11-01 00:46 沙漠中的鱼 阅读(1351) 评论(0)  编辑  收藏 所属分类: Flex

There are several techniques you can use to load and unload modules in your Flex applications. These techniques include:

When you're using modules in an AIR application, the module SWF must be located in the same directory as the main application SWF or one of its subdirectories.

Using the ModuleLoader class to load modules

You can use the ModuleLoader class to load module in an application or other module. The easiest way to do this in an MXML application is to use the <mx:ModuleLoader> tag. You set the value of the url property to point to the location of the module's SWF file. The following example loads the module when the application first starts:

<?xml version="1.0"?>
<!-- modules/MySimplestModuleLoader.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
<mx:ModuleLoader url="ColumnChartModule.swf"/>
</mx:Application>

You can change when the module loads by setting the value of the url property at some other time, such as in response to an event.

Setting the target URL of a ModuleLoader triggers a call to the loadModule() method. This occurs when you first create a ModuleLoader with the url property set. It also occurs if you change the value of that property.

If you set the value of the url property to an empty string (""), the ModuleLoader unloads the current module.

You can have multiple ModuleLoader instances in a single application. The following example loads the modules when the user navigates to the appropriate tabs in the TabNavigator container:

<?xml version="1.0"?>
<!-- modules/URLModuleLoaderApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
<mx:Panel 
        
title="Module Example" 
        height
="90%" 
        width
="90%" 
        paddingTop
="10" 
        paddingLeft
="10" 
        paddingRight
="10" 
        paddingBottom
="10"
    
>

        
<mx:Label width="100%" color="blue"
            text
="Select the tabs to change the panel."/>

        
<mx:TabNavigator id="tn"
            width
="100%" 
            height
="100%" 
            creationPolicy
="auto"
        
>
            
<mx:VBox id="vb1" label="Column Chart Module">
                
<mx:Label id="l1" text="ColumnChartModule.swf"/>
                
<mx:ModuleLoader url="ColumnChartModule.swf"/>
            
</mx:VBox>

            
<mx:VBox id="vb2" label="Bar Chart Module">
                
<mx:Label id="l2" text="BarChartModule.swf"/>
                
<mx:ModuleLoader url="BarChartModule.swf"/>
            
</mx:VBox>

        
</mx:TabNavigator>
    
</mx:Panel>
</mx:Application>

You can also use the ModuleLoader API to load and unload modules with the loadModule() and unloadModule() methods. These methods take no parameters; the ModuleLoader loads or unloads the module that matches the value of the current url property.

The following example loads and unloads the module when you click the button:

<?xml version="1.0"?>
<!-- modules/ASModuleLoaderApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
<mx:Script>
        
<![CDATA[
        import mx.modules.*;

        public function createModule(m:ModuleLoader, s:String):void {
            if (!m.url) {
                m.url = s;
                return;
            }
            m.loadModule();
        }
        
        public function removeModule(m:ModuleLoader):void {
            m.unloadModule();
        }
        
]]>
    
</mx:Script>

    
<mx:Panel title="Module Example" 
        height
="90%" 
        width
="90%" 
        paddingTop
="10" 
        paddingLeft
="10" 
        paddingRight
="10" 
        paddingBottom
="10"
    
>
        
<mx:TabNavigator id="tn" 
            width
="100%" 
            height
="100%" 
            creationPolicy
="auto"
        
>
            
<mx:VBox id="vb1" label="Column Chart Module">                
                
<mx:Button 
                    
label="Load" 
                    click
="createModule(chartModuleLoader, l1.text)"
                
/>
                
<mx:Button 
                    
label="Unload" 
                    click
="removeModule(chartModuleLoader)"
                
/>
                
<mx:Label id="l1" text="ColumnChartModule.swf"/>
                
<mx:ModuleLoader id="chartModuleLoader"/>                                
            
</mx:VBox>

            
<mx:VBox id="vb2" label="Form Module">
                
<mx:Button 
                    
label="Load" 
                    click
="createModule(formModuleLoader, l2.text)"
                
/>
                
<mx:Button 
                    
label="Unload" 
                    click
="removeModule(formModuleLoader)"
                
/>
                
<mx:Label id="l2" text="FormModule.swf"/>
                
<mx:ModuleLoader id="formModuleLoader"/>
            
</mx:VBox>
        
</mx:TabNavigator>
    
</mx:Panel>
</mx:Application>

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 load() method for that module.

When two classes of the same name but different implementations are loaded, the first one loaded is the one that is used. This can result in run-time errors. A common issue that occurs when using multiple modules is that the modules own class definitions that other modules want to use. Because they are in sibling application domains, the module that loaded the class definition first can use 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 Module domains.

Using the ModuleManager class to load modules

You can use the ModuleManager class to load the module. This technique is less abstract than using the <mx:ModuleLoader> tag, but it does provide you with greater control over how and when the module is loaded.

To use the ModuleManager to load a module in ActionScript, you first get a reference to the module's IModuleInfo interface by using the ModuleManager getModule() method. You then call the interface's load() method. Finally, you use the factory property of the interface to call the create() method and cast the return value as the module's class.

The IModuleInfo class's load() method optionally takes an ApplicationDomain and a SecurityDomain as arguments. If you do not specify either of these, then the module is loaded into a new child domain.

The following example shell application loads the ColumnChartModule.swf file and then adds it to the display list so that it appears when the application starts:

<?xml version="1.0"?>
<!-- modules/ModuleLoaderApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp()">
    
<mx:Script>
        
<![CDATA[
        import mx.events.ModuleEvent;
        import mx.modules.ModuleManager;
        import mx.modules.IModuleInfo;

        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();
        }
        
        private function modEventHandler(e:ModuleEvent):void {
            // Add an instance of the module's class to the
            // display list.
            vb1.addChild(info.factory.create() as DisplayObject);
        }
        
]]>
    
</mx:Script>

    
<mx:VBox id="vb1"/>

</mx:Application>

MXML-based modules can load other modules. Those modules can load other modules, and so on.

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.

Loading modules from different servers

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

Access applications across domains

  1. In your loading application, you must call the allowDomain() 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.
  2. 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.
  3. Load the cross-domain file on the remote server in the preinitialize event handler of your loading application.
  4. In the loaded module, call the allowDomain() method so that it can communicate with the loader.

The following example shows the init() method of the loading application:

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);
}

The following example shows the loaded module's init() method:

public function initMod():void {
Security.allowDomain("loaderservername");
}

The following example shows the cross-domain file that resides on the remote server:

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

For more information about using the cross-domain policy file, see Applying Flex Security.

Preloading modules

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 in the Flash Player or AIR 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.

When a module is loaded by the Flex application for the first time, the module's SWF file is transferred across the network and stored in the browser's cache. If the Flex 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.

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.

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.

To preload modules on application startup, use the IModuleInfo class load() method. This loads the module into memory but does not create an instance of the module.

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. 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.

<?xml version="1.0"?>
<!-- modules/PreloadModulesApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="preloadModules()">
    
<mx: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"
        }
        
]]>
    
</mx:Script>

    
<mx:Panel 
        
title="Module Example" 
        height
="90%" 
        width
="90%" 
        paddingTop
="10" 
        paddingLeft
="10" 
        paddingRight
="10" 
        paddingBottom
="10"
    
>

        
<mx:Label width="100%" color="blue"
            text
="Select the tabs to change the panel."/>

        
<mx:TabNavigator id="tn"
            width
="100%" 
            height
="100%" 
            creationPolicy
="auto"
        
>
            
<mx:VBox id="vb1" label="Column Chart Module">
                
<mx:Label id="l1" text="ColumnChartModule.swf"/>
                
<mx:ModuleLoader url="ColumnChartModule.swf"/>
            
</mx:VBox>

            
<mx:VBox id="vb2" label="Bar Chart Module">
                
<mx:Label id="l2" text="BarChartModule.swf"/>
                
<mx:ModuleLoader url="BarChartModule.swf"/>
            
</mx:VBox>
        
</mx:TabNavigator>
    
</mx:Panel>
</mx:Application>

引用: http://livedocs.adobe.com/flex/3/html/modular_5.html#171081


只有注册用户登录后才能发表评论。


网站导航: