22.10.与模块通信

22.10.1.问题
我想访问加载的模块和传递数据。
22.10.2.解决办法
使用mx.modules.ModuleLoader的child属性和mx.modules.IModuleInfo实例的factory属性,监听事件,调用公开方法,访问公开属性。
22.10.3.讨论
应用程序shell 通过ModuleLoader 和ModuleManager 的属性与被加载模块通信。对于<mx:Application>实例来说通信没有限制,因为模块也可以加载另一模块,使得被加载模块访问父模块和应用程序是一样的。

要访问加载模块的数据,你需要把指定载入实例的返回属性的类型重新映射为原来被载入的模块类。当使用<mx:ModuleLoader>对象时,可通过child属性获得模块实例:
+展开
-XML
<mx:Script>
<![CDATA[
private var myModule:MyModule;
private function moduleReadyHandler():void {
myModule = moduleLoader.child as MyModule;
myModule.doSomething();
}

]]>
</mx:Script>
<mx:ModuleLoader id="moduleLoaderurl="MyModule.swf"
ready="moduleReadyHandler();" />

当主应用程序可以访问被加载模块的数据时,moduleReadyHandler时间处理函数被调用。

<mx:ModuleLoader>的child属性类型重新映射为原模块类类型,现在你可以调用模块的公开方法访问其数据了。

而当使用ModuleManager 类为父应用程序时, 模块实例是通过IModuleInfo 的IFlexModuleFactory实例的create方法返回的:
+展开
-ActionScript
private var _moduleInfo:IModuleInfo;
private function creationHandler():void {
_moduleInfo = ModuleManager.getModule( 'MyModule.swf');
_moduleInfo.addEventListener( ModuleEvent.READY,moduleLoadHandler );
_moduleInfo.load();
}
private function moduleLoadHandler( evt:ModuleEvent ):void {
var myModule:MyModule = _moduleInfo.factory.create() as MyModule;
myModule.doSomething();
}

当ModuleLoader的child属性或IFlexModuleFactory.create方法返回值进行类型映射后,模块和主应用程序的联系分成紧密了,要想减少模块和它的类实例的紧密性,一般的做法是使用接口。使用接口,可使你的代码更具灵活性, 使你的主应用程序能连接更多的类实例。

为了例证当开发模块化应用程序时使用接口所产生的灵活性,我们假定创建一个供用户输入信息的表单模块。根据程序的步骤和变化,你可能发现你需要更多类型的表单。虽然他们可能显示不同的外观,或者对用户数据执行不同的操作,但是他们访问模块数据的方法却是一样的。采用实现接口的不同模块可增加你的应用程序的灵活性。

下面的例子是一个接口,列出了和用户信息相关的属性方法:
+展开
-ActionScript
package {
import flash.events.IEventDispatcher;
public interface IUserEntry extends IEventDispatcher {
function getFullName():String; 
function get firstName():String;
function set firstName( str:String ):void ;
function get lastName():String;
function set lastName( str:String ):void ;
}
}

创建实现此接口的模块,申明<mx:Module>的implements属性为IUserEntry接口:
+展开
-XML
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
implements="IUserEntrylayout="verticalwidth="100%height="100%">

<mx:Metadata>
[Event(name="submit", type="flash.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
private var _firstName:String;
private var _lastName:String;
public static const SUBMIT:String = "submit" ;
private function submitHandler():void {
firstName = firstNameInput.text;
lastName = lastNameInput.text;
dispatchEvent( new Event( SUBMIT ) );
}
public function getFullName():String {return _firstName + " "+ _lastName;}
[Bindable]
public function get firstName():String{return _firstName;}
public function set firstName( str:String ):void{_firstName = str;} 
[Bindable]
public function get lastName():String{return _lastName;}
public function set lastName( str:String ):void{_lastName = str;}

]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name:">
<mx:TextInput id="firstNameInputwidth="100%" />
</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput id="lastNameInputwidth="100%" />
</mx:FormItem>
<mx:Button label="submitclick="submitHandler();" />
</mx:Form>
</mx:Module>

这个模块提供一些控件供用户输入和提交用户信息。getter/setter 属性和getFullName方法将在模块的<mx:Script> 标签里实现。由实现IUserEntry 接口的mx.modules.Module 和mx.modules.ModuleBase类建立firstName和lastName的数据绑定。

要访问这里或其他实现IUserEntry接口的模块数据,父已运行必须对具体模块加载类的相应属性进行类型映射。

下面的例子使用<mx:ModuleLoader>的child属性实例访问实现IUserEntry模块的数据:
+展开
-XML
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Script>
<![CDATA[
private var myModule:IUserEntry;
private function moduleReadyHandler():void {
myModule = moduleLoader.child as IUserEntry;
myModule.addEventListener( "submit" , submitHandler );
}
private function submitHandler( evt:Event ):void {
welcomeField.text = 'Hello,'+myModule.getFullName();
trace( myModule.firstName + " "+ myModule.lastName );
}

]]>
</mx:Script>
<mx:ModuleLoader id="moduleLoaderurl="ContactEntry.swfready="moduleReadyHandler();" />
<mx:Label id="welcomeField" />
</mx:Application>

<mx:ModuleLoader>实例的ready事件处理函数建立对用户信息提交的事件处理器。当submitHandler方法被调用时,通过模块的getFullName实现打印一些字符串。把ModuleLoader实例的child属性类型映射为IUserEntry接口,是确保应用程序和模块之间的松耦合设计,这使得你可以动态的与实现统一接口的不同模块类交互。

父SWF访问模块数据没有限制,通过parentApplication属性模块也可以访问父应用程序数据:
+展开
-XML
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxmllayout="absolute"
creationComplete="creationHandler();">

<mx:Script>
<![CDATA[
private function creationHandler():void {
//Flex SDK 3.1.0里已找不到getInformation方法
infoField.text = parentApplication.getInformation();
}

]]>
</mx:Script>
<mx:Text id="infoField" />
</mx:Module>

当模块完成初始化后,creationHandler方法被调用,调用父应用程序getInformation方法返回的子节点组件信息。

模块的parentApplication属性继承自UIComponent超类,是一个Object类型。动态类Object是所有类的父类。因此你可以通过parentApplication实例访问数据而不用关心父类实现。也就是说模块也直接调用父应用程序的属性,不管其属性是否可用而引发的运行时异常。

一般来讲,模块是不应该访问父应用程序数据的,这是根据模块和父应用程序之间的松耦合设计原则决定的。为了减小这种联系,你可以把载入模块的应用程序映射为接口,就像上面的例子那样做。要确保不同的应用程序都能和同一个模块通信,强烈建议直接提供父应用程序数据给模块而不是通过动态parentApplication属性.做到了这些你就能轻松地开发模块化应用程序了。

加支付宝好友偷能量挖...


评论(0)网络
阅读(117)喜欢(0)flash/flex/fcs/AIR