2012-12-12 58 views
1

我想解析一个xml文件并在我的应用程序中动态加载Flex模块。但它每次只加载最后一个模块。我有一个单独的类来解析和加载模块。这里是类从XML文件加载flex模块

package 
{ 
import flash.events.Event; 
import flash.net.URLLoader; 
import flash.net.URLRequest; 

import mx.controls.Alert; 
import mx.events.ModuleEvent; 
import mx.modules.IModuleInfo; 
import mx.modules.ModuleLoader; 
import mx.modules.ModuleManager; 

public class VappModuleManager 
{ 

    private static var _instance:VappModuleManager; 
    private static const MODULE_PATH:String="./com/emc/vapp/"; 
    private static const MANIFEST_PATH:String="module-manifest.xml"; 
    private var _module:IModuleInfo; 
    private var _handler:Function; 
    private var loader:URLLoader; 
    public function VappModuleManager(object:SingletonEnforcer) 
    { 

    } 

    public function set handler(handler:Function):void 
    { 
     _handler=handler; 
    } 

    public static function get instance():VappModuleManager 
    { 
     if(_instance==null) 
     { 
      _instance=new VappModuleManager(new SingletonEnforcer());    
     } 

     return _instance; 
    } 


    public function load():void 
    { 
     loader = new URLLoader(); 
     loader.addEventListener(Event.COMPLETE, xmlLoaded); 
     loader.load(new URLRequest(MANIFEST_PATH)); 
    } 

    private function xmlLoaded(event:Event):void 
    { 
     Alert.show("Event Completed"); 
     var manifest:XML=new XML(event.target.data); 
     Alert.show(manifest.module.length()); 

     for (var index:int=0;index<manifest.module.length();index++) 
     { 
      Alert.show(MODULE_PATH+manifest.module[index][email protected]); 
      _module=ModuleManager.getModule(MODULE_PATH+manifest.module[index][email protected]); 
      _module.addEventListener(ModuleEvent.READY,_handler); 
      _module.load(); 
     } 
    } 


} 
} 
internal class SingletonEnforcer {} 

我使用上面的类如下。

moduleManager=VappModuleManager.instance; 

moduleManager.handler=myhandler; 

moduleManager.load(); 

我明白问题是与eventlistener变量“_module”,但不知道如何解决它。任何帮助赞赏。

回答

1

IModuleInfo.load的调用是异步的,因此您的for循环在任何模块加载之前已完全运行。此外,每次迭代循环时,您的职业等级_module属性将被新的Module实例覆盖。

我会建议通过等待READY事件顺序加载每个模块,并且只有在启动后才启动下一个模块的加载。当所有模块都被加载而不是执行回调函数时,我也会触发一个事件,因为这会给你更多的灵活性(例如多个对象可以监听一个事件)。

以下未测试,但应该给你的想法:

package 
{ 
    import flash.events.Event; 
    import flash.net.URLLoader; 
    import flash.net.URLRequest; 

    import mx.controls.Alert; 
    import mx.events.ModuleEvent; 
    import mx.modules.IModuleInfo; 
    import mx.modules.ModuleLoader; 
    import mx.modules.ModuleManager; 

    public class VappModuleManager 
    { 

     private static var _instance:VappModuleManager; 

     private static const MODULE_PATH:String="./com/emc/vapp/"; 
     private static const MANIFEST_PATH:String="module-manifest.xml"; 

     private var loader:URLLoader; 
     private var manifest:XML; 
     private var loadCount:int = 0; // track loaded modules 

     public function VappModuleManager(object:SingletonEnforcer) 
     { 

     } 

     public static function get instance():VappModuleManager 
     { 
      if(_instance==null) 
      { 
       _instance=new VappModuleManager(new SingletonEnforcer());    
      } 

      return _instance; 
     } 


     public function load():void 
     { 
      loader = new URLLoader(); 
      loader.addEventListener(Event.COMPLETE, xmlLoaded); 
      loader.load(new URLRequest(MANIFEST_PATH)); 
     } 

     private function xmlLoaded(event:Event):void 
     { 
      manifest =new XML(event.target.data); 

      // load the first module 
      loadModule(); 
     } 

     private function loadModule() { 
      // Use a locally scoped variable to avoid writing over the previous instance each time. 
      // You could push these onto an array if you need to be able to access them later 
      var module:IModuleInfo = ModuleManager.getModule(MODULE_PATH+manifest.module[loadCount][email protected]); 
      module.addEventListener(ModuleEvent.READY, moduleReadyHandler); 
      module.load(); 
     } 

     private function moduleReadyHandler(event:ModuleEvent) { 
      // Remove the event listener on the loaded module 
      IModuleInfo(event.target).removeEventListener(ModuleEvent.READY, moduleReadyHandler); 

      loadCount ++; 

      // Are there still modules in the manifest to load?    
      if (loadCount < manifest.module.length()) { 
       // Yes... load the next module 
       loadModule(); 
      } else { 
       // No... we're all finished so dispatch an event to let subscribers know 
       dispatchEvent(new Event("complete")); 
      } 
     } 
    } 
}