Flex2.01发布已经有段时间了,由今天开始,我们将陆续给您介绍Flex2.01中的一些新特性,帮助您更好的了解flex2.01,更好的进行flex应用的开发。

今天我们的主题是:模块化应用开发

做过Flex开发的朋友可能都已经在使用模块化的应用开发了,不过在Flex2.01以前,Flex中并没有单独的模块概念,我们只能使用<mx:Load/>导入其他模块应用,而这些模块应用其实也是一个可以独立运行的应用SWF文件,而在Flex2.01中,这里所谓的模块是不能直接运行但是可以直接被主应用导入、导出的swf文件。通过模块化,您可以按功能将一个大的应用切分为多个部分,然后在主应用中,根据业务流程调用的需要载入相应的模块,而在不需要的时候又可以卸载模块以释放内存占用,这样做的好处是显而易见的,你的应用不在需要在一启动的时候就导入所有的东西,这样可以减少应用载入的时间,免除漫长的等待,提高用户体验的效果。

具体的来说,模块化的应用开发有如下的好处:

  • 减少初始下载SWF文件的大小。
  • 更小的SWF文件就带来了更短的载入时间。
  • 更好的封装应用的各个相关部分,例如“报表”特性就可以分隔为一个独立的模块。

模块化应用

要创建一个模块化应用,您需要为每个模块创建单独的类,然后创建一个主应用来导入这些模块

创建模块化应用

  1. 创建任意数量的模块,MXML模块的根标签是<mx:Module>,而ActionScript模块要继承ModuleBase类。
  2. 就像编译应用一样编译每个模块。您可以使用mxmlc编译也可以使用flexBuilder编译,当然也可以使用我们昨天提到的Flex Ant Builder工具编译。
  3. 创建一个一般应用文件,这是个典型的根标签为<mx:Application>的MXML文件。当然也可以是一个ActionScript应用。
  4. 在应用文件中,使用<mx:ModuleLoader>载入模块,您也可以使用mx.modules.ModuleLoader的load()方法来载入。而对于继承ModuleBase的类老说,您必须使用ModuleManager类的方法来载入他们。

下面我们将创建一个非常简单的模块化应用,该应用有分别有两个模块,点击在主应用中载入按钮可以载入相应的模块,使用unload按钮可以卸载模块。

首先我们创建两个简单的MXML模块,MXML模块和Application相似,通过使用根标签<mx:Module>来继承了mx.modules.Module类就可以了,为了演示方便,我们的两个模块都简单的只放置的一个按钮。

fileName:module/Module1.mxml

[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;
    ]]>
  </mx:Script>
  <mx:Button label="first Module Button" click="Alert.show('i am the first module')"/>
</mx:Module>

fileName:module/Module2.mxml

[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;
    ]]>
  </mx:Script>
  <mx:Button label="second Module Button" click="Alert.show('i am the secend module')"/>
</mx:Module>

接着我们来编译模块,我们可以像编译普通的Application一样来编译模块,例如使用mxmlc编译如下:

[bash]
mxmlc Module1.mxml

这样编译出来模块文件大小和一般的应用的差不多大:135523字节,根据模块对相关组件的依赖关系,以上编译的SWF文件将链入所有flex框架中相关组件的代码,估计您也考虑到了,我们的模块是不能单独执行的,只有载入到应用中才能执行,这样模块就因为重复链入了一些应用已经链入的组件而增肥了不少,为了解决这样的问题,减少模块的大小,我们可以让模块编译时排除那些在应用已经包括的组件,包括自定义组件、框架组件等,这样模块中就只包含其依赖的而应用中没有包含的组件,就可以大大减少组件的大小。

要减少模块的大小,我们首先需要使用mxmlc命令生成一份要导入模块的应用的链接报告(linked report):

mxmlc -link-report=report.xml ModularApplicationSample.mxml

然后编译应用:

mxmlc ModularApplicationSample.mxml

以上两步骤也可以使用我们昨天发布的Flex Ant Task使用工程范例中的CompileAndGenerateLinkReport任务生成,该任务可以直接在源代码目录下生成命名为:mxml应用文件名_LinkReport.xml的链接报告。

然后再使用以上生成的链接报告编译模块,或者使用ant的CompileModuleWithLinkReport任务进行模块编译,注意需要传入mainApp参数来指明要导入模块的应用文件名。

mxmlc -load-externs=report.xml Module1.mxml

这样编译出来的文件将比开始编译的大小小很多,以上编译的大小为:21502,由135523变为21502,效果明显吧?!

当我们对模块进行修改时我们需要重新编译模块,但不需要重新编译导入该模块的应用,类似的,如果我们修改了导入该模块的应用,也不需要重新编译模块,除非我们的改动影响了链接报告的内容。

另外需要注意的是,如果为了减少模块大小使用了上面的load-externs选项编译模块,我们的模块可能与以后版本的flex不兼容,要让以后的版本的flex兼容我们的模块,我们需要重新编译我们的模块。

最后我们创建一个导入模块的应用,我们使用ModuleLoader组件的load()和unload()方法分别导入和导出组件:

fileName:ModularApplicationSample.mxml

[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="center">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;
      import mx.events.ModuleEvent;

      private function loadModule(url:String):void{
        moduleLoad.url=url;
        moduleLoad.loadModule();
      }
      private function unloadModule():void{
        moduleLoad.unloadModule();
      }
      private function errorHandler(e:ModuleEvent):void {
        Alert.show("There was an error loading the module." +
          " Please contact the Help Desk.");
        Alert.show(e.errorText);
      }
    ]]>
  </mx:Script>
  <mx:HBox>
    <mx:Button label="load Module1" click="loadModule('module/Module1.swf')"/>
    <mx:Button label="load Module2" click="loadModule('module/Module2.swf')"/>
    <mx:Button label="unload Module" click="unloadModule()"/>
  </mx:HBox>
  <mx:ModuleLoader id="moduleLoad" error="errorHandler(event)"/>
</mx:Application>

该示例中,点击load按钮将导入相应的模块,而点击unload按钮将卸载已经导入的模块。

查看示例|下载示例

到此我们就创建完成了一个简单的模块化应用,flex中的<mx:ModuleLoader />组件与以前的<mx:Loader />组件类似,其也有相应的导入模块状态监控时间,如:setupreadyloadingunloadprogresserrorurlChanged等事件,通过这些事件我们可以监听组件的载入状态,可以使用ProgressBar控件来显示组件的载入进度等,这些事件的使用,我们这里就不多说,Flex2.01的文档对此有详细的说明。

Flex2.01中模块概念的引人,使得Flex开发又向成熟的开发语言迈进了一步,相信随着后续Flex版本的推出,Flex将会更加成熟,更加适合成熟的企业开发市场。