Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3252022
  • 博文数量: 530
  • 博客积分: 13360
  • 博客等级: 上将
  • 技术积分: 5473
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-13 13:32
文章分类

全部博文(530)

文章存档

2017年(1)

2015年(2)

2013年(24)

2012年(20)

2011年(97)

2010年(240)

2009年(117)

2008年(12)

2007年(8)

2006年(9)

分类:

2010-08-18 11:46:31

更新日期:2010.8.20
1.本例目的
    使用Parsley,进行模块化
   
2.本例开发环境
      parsley2.2.2, flex_sdk_4.1.0.16076,flash buider 4

3.Application加载模块后,模块之间互相通信
功能:
      通过ModuleLoader加载两个module,并且在两个module之间发送消息
      这个程序只对界面实体类托管,而不对界面类托管,有利于减少界面类反射花费的时间,值得推荐

(1)创建一个消息类,用于两个module之间的消息通信
TestEvent.as
    public class TestEvent extends Event
    {
        public static const TEST:String = "testEvent";
        private var _message:String;
        private var _sender:String;
        public function TestEvent( message:String, sender:String=null ) {
            super( TEST );
            _message = message;
            _sender = sender;
        }
        public function get message():String {
            return _message;
        }
        public function get sender():String {
            return _sender;
        }
        override public function clone() : Event {
            return new TestEvent( message, sender );
        }
    }

(2)创建一个全局类,保存全局信息
GlobalData.as
    [Bindable]
    public class GlobalData
    {
        /**
         * 保存模块间通信的信息
         */
        public var items:ArrayCollection = new ArrayCollection();
       
        /**
         * 在parsley的Context中初始化 count
         */
        public var count:int = 0;
       
        public function incrementedCount():int {
            return ++count;
        }
    }

(3)创建主界面
主界面只是用于显示两个module,并初始化上下文
ParsleyModuleExam1.mxml
    creationComplete="creationCompleteHandler(event)"
   
       
   

   
                    import mx.events.FlexEvent;
            protected function creationCompleteHandler(event:FlexEvent):void {
                module1Loader.loadModule( "module1/Module1.swf" );
                module2Loader.loadModule( "module2/Module2.swf" );
            }
        ]]>
   

   
       
       
   


(4)创建上下文配置文件

    xmlns:fx=""
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:spicefactory="">
   
                    import shell.ShellPanelPM;
            import common.GlobalData;
        ]]>
   

   
       
       
            5
       

   


说明
      这里只初始化了两个类ShellPanelPM和GlobalData
      ShellPanelPM是module中界面实体类,这样一来两个module共用一个ShellPanelPM
      这里对GlobalData的count变量进行了初始化,该值用于表示消息发送的序号
      模块的contex由加载module时再初始化,有利于减少内存,提高速度。

模块1和模块2代码相同,这里只给出一个模块的代码

(5)创建module界面类
Module1.mxml
这个module,只包含了一个自定义视图组件Module1Panel,有利于代码的复用
    xmlns:fx=""
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:parsley=""
    xmlns:module1="module1.*"
    layout="vertical" width="100%"
    preinitialize="FlexContextBuilder.build(Module1Context,this)">
   
   
                    import org.spicefactory.parsley.flex.FlexContextBuilder;
        ]]>
   

   

说明
      本人曾想把FlexContextBuilder.build(Module1Context,this),改成
           
      但是,报
           1172: 找不到定义 Module1Context
      无语

(6)创建模块1的Context
Module1Context.mxml

    xmlns:mx=""
    xmlns=""
    xmlns:mod1="module1.*">
   


(7)创建自定义组件类Module1Panel
Module1Panel.mxml
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:mx="library://ns.adobe.com/flex/mx"
         addedToStage="dispatchEvent(new Event('configureIOC', true))"
         title="Module #1 Panel"
         width="400" height="300">
   
       
   

   
                    [Inject]
            [Bindable]
            public var model:Module1PanelPM;
        ]]>
   

   
   
                    text="{model.textReceive}"
                />
   
                    change="model.textSend=messageText.text"/>
   
       
   


界面如下

注意:
      语句addedToStage="dispatchEvent(new Event('configureIOC', true))"不能删,否则module将无法使用parsley中的上下文
      即使是binding,当textArea的内容发生改变时,也必须使用change="model.textSend=messageText.text",将值传递给model


(8)创建Module1Panel对应的实体类
Module1PanelPM.as
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import common.GlobalData;
    import common.TestEvent;
   
    [Event( name="testEvent", type="common.TestEvent" )]
    [ManagedEvents( "testEvent" )]
    public class Module1PanelPM extends EventDispatcher
    {
        [Bindable]
        public var textReceive:String = "Initial string";
       
        [Bindable]
        public var textSend:String = "";
       
        [Inject]
        [Bindable]
        public var globalData:GlobalData;
       
        public function Module1PanelPM(target:IEventDispatcher=null) {
            super(target);
        }
        public function sendMessage() : void {
            globalData.incrementedCount();
            dispatchEvent( new TestEvent( textSend, "Module1" ) );
        }
        [MessageHandler]
        public function onMessage( event : TestEvent ) : void {
            textReceive = "[" + globalData.count + "] ";
            if( event.sender != null )
                textReceive += event.sender + ": ";
            textReceive += event.message;
        }
    }
说明
      [ManagedEvents( "testEvent" )] :表示这个类对托管消息进行操作
      GlobalData:这个类来自Application

程序运行界面

说明
      当从module1发消息TestEvent时,所有的module都接收到这个消息,并通过 [MessageHandler]进行处理,通过textReceive += event.message;将消息内容显示在界面上。

4.Application与模块之间通信
功能
       本例子用于演示Application与模块之间的通信
       有个Parsley框架之后,Application与消息之间的通信都是通过Parsley框架完成的,其实也就很简单了,呵呵
本例绝大部分代码来自上例
(1)主应用程序
ParsleyModuleExam2.mxml
与上例的ParsleyModuleExam1.mxml相比,添加一个消息发送与接收组件ShellPanel和监控组件DataMonitor。
ShellPanel与Module1Panel相同,DataMonitor组件用于显示所有模块和应用程序派发的消息。
   
       
       
   


(2)组件DataMonitor
DataMonitor.mxml
该组件用于显示所有模块和主程序派发的消息

         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:mx="library://ns.adobe.com/flex/mx"
         title="Message Monitor Panel"
         addedToStage="dispatchEvent(new Event('configureIOC', true))">
   
       
   

   
   
                    import org.spicefactory.lib.logging.LogContext;
            import org.spicefactory.lib.logging.Logger;
            import common.GlobalData;
            import common.TestEvent;
           
            private static const log:Logger = LogContext.getLogger(DataMonitor);
           
            [Inject]
            [Bindable]
            public var model:GlobalData;
           
            [MessageHandler]
            public function onMessage( event : TestEvent) : void {
                var text:String = "";
                if( event.sender != null )
                    text += event.sender + ": ";
                text += event.message;
                log.debug( "Message handler, message = '{0}'", text );
                model.items.addItem( text );
            }
        ]]>
   

   


界面显示如下


5.利用程序打开module
(1)主程序
ParsleyModuleExam3.mxml
主程序有二个相同的module,一个通过程序创建,一个通过moduleLoader创建
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:parsley=""
               xmlns:app="shell.*"
               creationComplete="creationCompleteHandler(event)"
               addedToStage="dispatchEvent(new Event('configureView', true));"
               minWidth="955" minHeight="600">
   
       
   


   
       
   

   
   
                    import mx.events.FlexEvent;
            import shell.Module3Window;
            import org.spicefactory.parsley.core.context.Context;

            [Inject]
            public var context:Context;

            private function onModule1Button():void {
                //创建组件Module3Window ,里面包含ModuleLoader
                var window:Module3Window = new Module3Window();
                //将组件的上下文添加到根视图上
                context.viewManager.addViewRoot(window);
                this.addElement(window);
            }
            protected function creationCompleteHandler(event:FlexEvent):void {
                module2Loader.loadModule( "module1/Module1.swf" );
            }
        ]]>
   

   
   

注意
     这里不能将url直接写在ModuleLoader内,否则提示无法在主程序初始化时加载模块,必须写在creationComplete事件内

(2)组件Module3Window
Module3Window.mxml
这个窗体包含了ModuleLoader,当加载模块时,显示Loading,加载完成后,显示模块
    creationComplete="init()"
   
                    import mx.events.ModuleEvent;
            private function init():void {
                currentState = "loading";
                module3Module.addEventListener(ModuleEvent.READY,onModuleReady);
                module3Module.loadModule("module1/Module1.swf");
            }
            private function onModuleReady(event:ModuleEvent):void {
                module3Module.removeEventListener(ModuleEvent.READY,onModuleReady);
                currentState = "loaded";
            }
        ]]>
   

   
       
       
   
   
       
           
       

   

   
注意
      移除监听器是个好习惯,否则将影响内存回收

其它程序参见上例。

程序运行界面如下


6.ViewStack与Module相结合使用
(1)主程序
ParsleyModuleExam4.mxml
ViewStack中视图的切换通过自定义事件ViewChangeEvent进行
   
        [Event(name="view.inbox",type="shell.ViewChangeEvent")]
        [Event(name="view.provider",type="shell.ViewChangeEvent")]
        [Event(name="view.debug",type="shell.ViewChangeEvent")]
        [ManagedEvents("view.inbox,view.provider,view.debug")]
   

说明:定义了三个托管事件,当点击按钮时派发
   
       
   

说明:这里本可以不要上下文配置,但是去除后,则程序出错,不知为什么?
   
       
           
               
               
               
           

           
       

   

说明:定义了三个按钮和一个组件ContentRegion ,该组件中包含了一个ViewStack

(2)组件ContentRegion
ContentRegion.mxml
          xmlns:s="library://ns.adobe.com/flex/spark"
          xmlns:mx="library://ns.adobe.com/flex/mx"
          xmlns:shell="shell.*"
          paddingBottom="5" paddingLeft="10" paddingRight="10" paddingTop="10">
   


(3)组件ContentViewStack
ContentViewStack.mxml
ViewStack包含了四个视图,通过Parsley的消息框架接收消息并控制显示哪一个视图
              xmlns:s="library://ns.adobe.com/flex/spark"
              xmlns:shell="shell.*"
              addedToStage="dispatchEvent( new Event( 'configureIOC', true ) ); this.selectedIndex=0">
   
                    [MessageHandler]
            public function handleViewChange(event:ViewChangeEvent):void {
                var newIndex:int = 0;
                if( event.type == ViewChangeEvent.INBOX ) {
                    newIndex = 1;
                } else if( event.type == ViewChangeEvent.PROVIDER ) {
                    newIndex = 2;
                } else if( event.type == ViewChangeEvent.DEBUG ) {
                    newIndex = 3;
                }
                this.selectedIndex = newIndex;
            }
           
        ]]>
   

   
       
           
       

   

                           width="100%" height="100%" />
                              width="100%" height="100%" />
   
       
           
       

   


说明
      InboxLoader 和ProviderLoader 里包含有ModuleLoader
      InboxLoader 和ProviderLoader 代码结构相同,这里只列出一个模块代码

(4)组件InboxLoader
InboxLoader.mxml
这是一个模块调用组件
         creationComplete="init()">
   
                    import mx.events.ModuleEvent;
            private function init():void {
                if(inboxModule.url==null)
                    inboxModule.loadModule("inbox/InboxModule.swf");
            }
        ]]>
   

   


(5)InboxModule
InboxModule.mxml
这是一个模块,里面有一个自定义视图组件
          xmlns:s="library://ns.adobe.com/flex/spark"
          xmlns:mx="library://ns.adobe.com/flex/halo"
          width="100%" height="100%"
          addedToStage="dispatchEvent(new Event('configureIOC',true))">
   
                    [Inject]
            [Bindable]
            public var model:InboxContainerPM;
        ]]>
   

   
   


(6)界面实体类
InboxContainerPM
这是InboxContainer视图对应的实体类,需要在Context中声明一下,这里就不列出了。
    public class InboxContainerPM extends EventDispatcher
    {
       
        private var _items:ArrayCollection = new ArrayCollection();
        public function InboxContainerPM(target:IEventDispatcher=null) {
            super(target);
        }
        [Bindable] public function get items():ArrayCollection {
            return _items;
        }
        public function set items(items:ArrayCollection):void {
            _items = items;
        }
        [Init]
        public function init():void {
            var array:Array = [ "Line 1", "Line 2", "Line 3" ];
            _items.source = array;
        }
    }
说明
     Init标签是Parsley的,表示在这个类初始化时执行。

界面运行如下


总结
1.代码详见:ParsleyModuleProject_2010820.zip
  还有一个项目ParsleyModuleProject2_2010820.zip的代码没有在这列出,功能与此类似,可以参考
2.这次只是初步能使用模块,但还有一些问题值得深入研究
        主程序的Context和模块的Context如何加载和卸载。
3.Cairngorm3中有基于Parsley 模块化的扩展,值得一看

参考文献
1. %20module%20mxml&d=0
阅读(2770) | 评论(0) | 转发(0) |
0

上一篇:java TCP+BIO入门

下一篇:java TCP+nio入门

给主人留下些什么吧!~~