zoukankan      html  css  js  c++  java
  • 打造模块化的TWaver Flex应用

    当Flex应用越来越庞大时,问题会越来越多:
    1. SWF文件的大小也会越来越大;
    2. 下载SWF文件的时间也会越来越长;
    3. 如果有多个Flex应用,如何复用相同的代码(包括Flex Framework、自定义组件库和第三方包,比如TWaver Flex);
    4. 每次升级后,用户都需要重新下载新的SWF文件;
    5. 如何在不修改并编译旧SWF文件的情况下,增加新功能;

    如何解决这些问题?
    一、 使用动态共享库(Runtime Shared Libraries)。Flex Framework、自定义组件库和第三方包都是独立的swf文件,Flex应用程序中将不包含Flex Framework、自定义组件库和第三方包的代码,所以:
    1. 程序修改后,只要更新用户程序代码即可,不用更新Flex Framework、自定义组件库和第三方包;
    2. RSL被浏览器缓存了,更新用户程序后,RSL不用重新下载;
    3. 多个Flex应用可以共享一份RSL,不用重复下载;

    二、使用模块化(Modular)。各个功能模块被拆分成不同的SWF文件,所以:
    1. 可以单独更新某个功能模块;
    2. 可以动态添加模块;

    不过单单使用RSL或者Modular,并不能解决所有问题:
    1. 仅仅使用RSL时,无法将功能模块拆分,无法动态加载功能模块;
    2. 仅仅使用Modular时,无法去除所有模块用到的公共的Flex Framework、自定义组件库和第三方包,导致子模块文件过于庞大;

    本文详细介绍了RSL和Modular的结合,帮您打造模块化的、可扩展的、强健的TWaver Flex应用。

    一、为了避免主程序和子模块之间的高度耦合,需要创建一个Flex Library工程,此工程定义了所有子模块用到的公共类,以及子模块和主程序之间通讯的接口:
    1. IModule接口:子模块实现此接口,用于主程序显示子模块的名称(get title),以及子模块加载完毕后,回调子模块(ready)

    package demo {
    public interface IModule {
    function get title():String;
    function ready(app:IApplication):void;
    }
    }
    

    2. IApplication接口,主程序实现此接口,用于子模块和主程序交互,目前此接口无任何方法,可自行根据需要添加  

    package demo {
    public interface IApplication {
    
    }
    }
    

      另外此Library工程还自定义了Network组件、Node,供子模块使用,这里不一一列出,具体参考附件的源代码。不过需要注意的是,工程选项里,framework linkage和twaver.swc的link type必须改成external,以减小Library工程生成的swc文件的大小。

    二、创建主程序Flex工程,此工程引用上面的Library工程以及twaver.swc。实现的功能为左边显示Tree,点击树节点后,右边加载相应的子模块。
    1. 添加组件标签,初始化界面,首先是一HDividedBox组件,左边为FastTree,右边为VBox;VBox里上面为Label,显示子模块名称,下面为子模块容器:

    <mx:HDividedBox width="100%" height="100%">
    <tw:FastTree id="tree" width="300" height="100%"/>
    <mx:VBox width="100%" height="100%">
    <mx:Label id="title" width="100%" textAlign="center"/>
    <mx:Canvas id="content" width="100%" height="100%"/>
    </mx:VBox>
    </mx:HDividedBox>
    

     

    2. 初始化树节点:为了实现动态添加模块,这里从xml文件读取模块信息。以后添加新模块时,直接修改xml文件即可,不用修改主程序。
    xml文件包含模块名称和模块url:

    <modules>
    <module name="PSTN" url="ModulePSTN.swf"/>
    <module name="Alarm" url="ModuleAlarm.swf"/>
    </modules>
    

         加载xml文件代码如下,主要是将url信息存到client属性中,用于点击该节点时用此url加载子模块:

    private function initTreeBox():void {
    var httpService:HTTPService = new HTTPService();
    httpService.resultFormat = "e4x";
    httpService.addEventListener(ResultEvent.RESULT, this.addModules);
    httpService.url = "modules.xml";
    httpService.send();
    }
    
    private function addModules(e:ResultEvent):void {
    for each(var module:XML in e.result.module){
    this.addModule(module.@name, module.@url);
    }
    }
    
    private function addModule(name:String, url:String):void {
    var data:Data = new Data();
    data.name = name;
    data.setClient("url", url);
    this.tree.dataBox.add(data);
    }
    

      3. 添加Tree的选中监听:当树节点被选中时,先判断对应的子模块是否加载过,如果未加载过,则动态加载之,并将加载的模块存入client属性中,否则直接将之前存储在client属性中的子模块加入右边容器中:

    this.tree.selectionModel.addSelectionChangeListener(this.handleSelectionChangeEvent);
    
    private function handleSelectionChangeEvent(e:SelectionChangeEvent):void {
    var selectedData:IData = this.tree.selectionModel.lastData;
    if(selectedData){
    var moduleLoader:ModuleLoader = selectedData.getClient("module");
    if(moduleLoader){
    this.content.removeAllChildren();
    this.content.addChild(moduleLoader);
    this.title.text = (moduleLoader.child as IModule).title;
    }else{
    moduleLoader = new ModuleLoader();
    moduleLoader.percentWidth = 100;
    moduleLoader.percentHeight = 100;
    moduleLoader.addEventListener(ModuleEvent.READY, this.moduleReady);
    moduleLoader.loadModule(selectedData.getClient("url"));
    selectedData.setClient("module", moduleLoader);
    }
    }
    }
    
    private function moduleReady(event:ModuleEvent):void {
    var moduleLoader:ModuleLoader = event.target as ModuleLoader;
    var module:IModule = moduleLoader.child as IModule;
    content.removeAllChildren();
    content.addChild(moduleLoader);
    this.title.text = module.title;
    module.ready(this);
    }
    

      注意,引用twaver.swc和Library工程时,twaver.swc必须在Library工程的上面,否则会报找不到twaver.network::Network类,而且framework linkage,twaver.swc以及上面的Library工程的link type必须为Runtime shared library(RSL),具体设置见下面第三步。

    三、创建子模块Flex工程,这里以Demo里的PSTNDemo和AlarmPropagationDemo为例,创建2个子模块工程,子模块工程为Flex工程,编译选项里,framework linkage,twaver.swc以及上面的Library工程的link type必须为Runtime shared library(RSL)。不过需要注意的是,如果twaver.swc是通过“Add SWC Folder”添加的话,link type就没有Runtime shared library(RSL)这个选项,这或许是Flash Builder的bug,但如果是用”Add SWC”添加的,就没这个问题,见下图:

      


    另外,子模块的编译路径可以修改为主程序工程的bin-debug目录,免得每次修改子模块后,需要复制子模块swf到主程序的bin-debug中:

    还有,不用生成HTML Wrapper,因为子模块不能独立运行,只能从主程序中加载,所以没有必要生成包装子模块的html文件:

    最后,要注意的是,修改link type为RSL时,如果没有添加RSL路径,OK按钮是不能点的,只能点击”Add“按钮,添加RSL路径后,才能点击OK按钮,这点很坑爹:

         子模块的代码比较简单,需要注意的是mxml文件的根标签要改为Module,还有要实现IModule接口:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:demo="http://www.demo.com/demo" implements="demo.IModule"
    xmlns:tw="http://www.servasoftware.com/2009/twaver/flex"
    creationComplete="init()" width="100%" height="100%">
    <mx:Script>
    <![CDATA[
    import demo.*;
    
    private var _app:IApplication = null;
    
    public function get title():String {
    return "Alarm Demo";
    }
    
    public function ready(app:IApplication):void {
    this._app = app;
    }
    ]]>
    </mx:Script>
    </mx:Module>
    

      经过了这么多繁琐的步骤,终于可以测试一下程序了:


          再看看子模块、Library工程以及主程序的包大小(子模块只有50K不到,的确够小了):


    关于更多Modular和RSL的内容,请参考Adobe官方文档:
    Creating Modular Applications
    Using Runtime Shared Libraries
    本文完整Demo见附件:ModuleDemo

  • 相关阅读:
    apache安全—用户访问控制
    hdu 3232 Crossing Rivers 过河(数学期望)
    HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
    UVA 11020 Efficient Solutions (BST,Splay树)
    UVA 11922 Permutation Transformer (Splay树)
    HYSBZ 1208 宠物收养所 (Splay树)
    HYSBZ 1503 郁闷的出纳员 (Splay树)
    HDU 5416 CRB and Tree (技巧)
    HDU 5414 CRB and String (字符串,模拟)
    HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
  • 原文地址:https://www.cnblogs.com/twaver/p/2494409.html
Copyright © 2011-2022 走看看