zoukankan      html  css  js  c++  java
  • Flex中ModuleManager的一个bug

    估且认为它是一个bug吧,因为到目前为止还是没想明白造成问题的原因。

    在相对较为复杂或是多人协作的flex项目开发中,使用module进行开发是很平常的事情,而module的加载一般常用的有两种方法:

    1、使用ModuleLoader加载器;

    2、使用ModuleManager进行加载;

    使用ModuleLoader进行加载:

    <mx:ModuleLoader id="moduleLoader" right="10" top="10"/>

    //
    private function loadModule(url:String):void
    {
    if (moduleLoader.url)
    {
    moduleLoader.unloadModule();
    }

    moduleLoader.url = url;
    }

    使用ModuleManager进行加载:

    private function load(url:String):void
    {
    var tempModuleInfo:IModuleInfo = ModuleManager.getModule(url);

    tempModuleInfo.addEventListener(ModuleEvent.READY, onReady);
    tempModuleInfo.addEventListener(ModuleEvent.PROGRESS, onProgress);
    tempModuleInfo.addEventListener(ModuleEvent.ERROR, onError);
    tempModuleInfo.addEventListener(ModuleEvent.SETUP, onSetup);

    tempModuleInfo.load(ApplicationDomain.currentDomain);
    }

    //...
    private function onReady(evt:ModuleEvent):void
    {
    var tempModuleInfo:IModuleInfo = evt.target as IModuleInfo;

    container.addChild(tempModuleInfo.factory.create() as DisplayObject);
    }
     
    ModuleManager类负责管理加载的模块,当将模块的url传递到public的ModuleManager.getModule方法中时,则该模块位置就添加到被管理模块的列表中,并返回一个mx.modules.IModuleInfo的实例。
    ModuleInfo对象负责加载swf文件,并被封装成一个实现了IModuleInfo接口的代理类,由ModuleManager.getModule方法返回,可以监听代理类上的状态事件,比如:ready、error、setup、progress事件等.
     
    mx.events.ModuleEvent类
    常量 字符串值 描述
    PROGRESS "progress" 加载模块时被调度。可以用这个事件访问被加载模块的bytesLoaded和bytesTotal属性
    SETUP "setup" 当已加载了足够的模块内容时被调度
    READY "ready" 当模块完成加载时被调度
    UNLOAD "unload" 当卸载模块时被调度
    ERROR "error" 当模块下载过程中出错时被调度

    但我在写实际的demo示例时,发现一个问题,如果没有事先声明IModuleInfo类的实例,在使用上面方面加载模块时,第一次加载不会调用任何的方法。完成的示例代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600"
    creationComplete="inited()">

    <mx:Script>
    <![CDATA[
    import mx.events.ModuleEvent;
    import mx.modules.IModuleInfo;
    import mx.modules.ModuleManager;

    private var module_1_url:String = "com/modules/OneModule.swf";
    private var module_2_url:String = "com/modules/TwoModule.swf";

    private var _moduleInfo:IModuleInfo;

    private function inited():void
    {

    }

    private function loadModule(type:Number):void
    {
    var url:String;

    if (type === 1)
    {
    url = module_1_url;
    }
    else
    {
    url = module_2_url;
    }

    var tempModuleInfo:IModuleInfo = ModuleManager.getModule(url);

    //注释或使用下面一行,运行查看不同的效果
    _moduleInfo = tempModuleInfo;

    tempModuleInfo.addEventListener(ModuleEvent.READY, onReady);
    tempModuleInfo.addEventListener(ModuleEvent.PROGRESS, onProgress);
    tempModuleInfo.addEventListener(ModuleEvent.ERROR, onError);
    tempModuleInfo.addEventListener(ModuleEvent.SETUP, onSetup);

    tempModuleInfo.load(ApplicationDomain.currentDomain);
    }

    private function onSetup(evt:ModuleEvent):void
    {

    }

    private function onProgress(evt:ModuleEvent):void
    {
    msg.htmlText = "正在加载:" + Math.floor(evt.bytesLoaded / evt.bytesTotal).toString() + "%";
    }

    private function onReady(evt:ModuleEvent):void
    {
    var moduleInfo:IModuleInfo = evt.target as IModuleInfo;

    moduleInfo.removeEventListener(ModuleEvent.PROGRESS, onProgress);
    moduleInfo.removeEventListener(ModuleEvent.READY, onReady);
    moduleInfo.removeEventListener(ModuleEvent.ERROR, onError);

    msg.htmlText = "模块加载完成";

    moduleCanvas.addChild(moduleInfo.factory.create() as DisplayObject);
    }

    private function onError(evt:ModuleEvent):void
    {
    msg.htmlText = "模块加载出错!";
    }


    private function useLoader():void
    {
    if (moduleLoader.url)
    {
    moduleLoader.unloadModule();
    }

    moduleLoader.url = module_1_url;
    }
    ]]>
    </mx:Script>

    <mx:Text id="msg" />


    <mx:HBox width="400" horizontalGap="10" y="50" x="50">
    <mx:Button label="动态加载模块一" click="loadModule(1)" />
    <mx:Button label="动态加载模块二" click="loadModule(2)" />
    <mx:Spacer width="50" />
    <mx:Button label="使用加载器" click="useLoader()" />
    </mx:HBox>

    <mx:ModuleLoader id="moduleLoader" right="10" top="10"/>

    <mx:Tile horizontalGap="10" width="100%" id="moduleCanvas" y="100" />

    </mx:Application>

    在上面例子中,事先已经声明过了一个IModuleInfo类的实例,在加载时如果使用该实例进行加载则一切正常,如果不使用已经被声明过的实例加载,则第一次加载时,不会有任何的反应,但使用ModuleLoader是没有此问题的,所以我只能认为这是一个bug了

    示例项目工程的目录很简单:

    image

    如果想使用ModuleManager加载模块,保险的方式就是先声明一个IModuleInfo类的实例,然后使用该实例去加载模块。两种加载模块的优先方法相比,一般更为常用的是第二种,因为可以预加载模块,比较容易按不同的需求来控制模块。

  • 相关阅读:
    PAT 甲级 1040 Longest Symmetric String
    POJ 1276 Cash Machine
    #Leetcode# 349. Intersection of Two Arrays
    #Leetcode# 922. Sort Array By Parity II
    【USACO题库】3.1.2 Score Inflation总分
    【USACO题库】3.4.4 Raucous Rockers“破锣摇滚”乐队
    【USACO题库】3.4.2 American Heritage美国血统
    【USACO题库】3.3.5 A Game游戏
    【USACO题库】3.3.4 Home on the Range家的范围
    【USACO题库】3.3.1 Riding the Fences骑马修栅栏
  • 原文地址:https://www.cnblogs.com/meteoric_cry/p/2234982.html
Copyright © 2011-2022 走看看