Flex Viewer通过DataManager提供数据共享服务,各个模块可通过事件进行数据共享和数据获取。DataManager负责将共享数据以key-value的形式存储于内存,并随时准备接收和派发共享数据。先来分析一下DataManager的代码:
public class DataManager extends EventDispatcher{
private var dataTable:Hashtable; ①
public function DataManager(){ super(); dataTable=new Hashtable(); ViewerContainer.addEventListener(AppEvent.CONFIG_LOADED, config);② //this is a example to setup the listner to get the type of data the Data //Manager is interested in. ViewerContainer.addEventListener(AppEvent.DATA_FETCH_ALL, fetchAllData);③ ViewerContainer.addEventListener(AppEvent.DATA_PUBLISH, addData);④ ViewerContainer.addEventListener(AppEvent.DATA_FETCH, fetchData);⑤ }
private function config(event:AppEvent):void{ }
private function fetchAllData(event:AppEvent):void{⑥ ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_SENT, dataTable)); }
private function fetchData(event:AppEvent):void{⑦ var key:String=event.data.key as String; var data:Object={key: key, collection: dataTable.find(key)}; ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_SENT, data)); }
private function addData(event:AppEvent):void{⑧ var key:String=event.data.key; if (key){ var dataCollection:Object=event.data.collection; if (dataTable.containsKey(key)){ dataTable.remove(key); } dataTable.add(key, dataCollection); //var data:Object={key: key, data: dataTable}; // change by ropp to just send new published data var data:Object={key: key, data: dataCollection}; ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_NEW_PUBLISHED, data)); } } } |
① 哈希表实例,用来以key-value的形式存储共享数据;
② 监听CONFIG_LOADED事件;
③ 监听DATA_FETCH_ALL(获取所有共享数据)事件;
④ 监听DATA_PUBLISH(发布共享数据)事件;
⑤ 监听DATA_FETCH(根据key获取共享数据)事件;
⑥ DATA_FETCH_ALL事件响应方法;
⑦ DATA_FETCH事件响应方法,根据key返回对应的共享数据;
⑧ DATA_PUBLISH事件响应方法,将发布的共享数据保存,并将最新的共享数据分发出去(DATA_NEW_PUBLISHED事件)。此处源代码有一点小问题,修改见注释。
再来看一下BaseWidget对共享数据的支持,BaseWidget有如下代码:
/** * Add information from a widget to the DataManager so that it can be shared between widgets. * @param key the widget name * @param arrayCollection the list of object in infoData structure. */ public function addSharedData(key:String, arrayCollection:ArrayCollection):void{① var data:Object = { key: key, collection: arrayCollection }; ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_PUBLISH, data)); } /** * Fetch shared data from DataManager. */ public function fetchSharedData():void{② ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_FETCH_ALL)); } /** * Fetch share data from DataManager by key * @param key */ public function fetchShareDataByKey(key:String):void{③新添加方法 ViewerContainer.dispatchEvent(new AppEvent(AppEvent.DATA_FETCH, {key:key})); } |
① addShareData()方法用来向DataManager发布共享数据;
② fetchShareData()方法用来向DataManager请求所有的共享数据;
③ fetchShareDataByKey()方法在BaseWidget中未提供,我们不妨把这个方法加上去,用来向DataManager请求以key存储的共享数据。
下面实现一个HelloDataManagerWidget来说明如何发布和获取共享数据,代码如下:
<?xml version="1.0" encoding="utf-8"?> <viewer:BaseWidget xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:viewer="com.esri.viewer.*" creationComplete="init()"> <fx:Script> <![CDATA[ import com.esri.viewer.AppEvent; import com.esri.viewer.ViewerContainer; import com.esri.viewer.utils.Hashtable; import mx.collections.ArrayCollection;
private function init():void{① ViewerContainer.addEventListener(AppEvent.DATA_SENT, dataSentHandler); ViewerContainer.addEventListener(AppEvent.DATA_NEW_PUBL ISHED, dataNewPublishedHandler); }
private function dataSentHandler(event:AppEvent):void{② if (event.data is Hashtable){ var keyValue:String=""; var table:Hashtable=Hashtable(event.data); var keySet:Array=table.getKeySet(); for each (var key:String in keySet){ keyValue+="key: " + key + "; value: " + String(table.find(key)) + "/n"; } allValue.text=keyValue; } else if (event.data.collection) fValue.text=event.data.collection[0]; }
private function dataNewPublishedHandler(event:AppEvent):void{③ var data:Object=event.data; var key:String=data.key; var value:String=data.data[0]; this.nKey.text=key; this.nValue.text=value; }
private function shareData():void{④ this.addSharedData(key.text, new ArrayCollection([value.text])); }
private function fetchByKey():void{⑤ this.fetchShareDataByKey(fKey.text); }
private function fetchAll():void{⑥ this.fetchSharedData(); } ]]> </fx:Script> <viewer:WidgetTemplate width="500" height="300"> <s:VGroup width="100%" height="100%"> <s:HGroup width="100%" verticalAlign="middle"> <s:Label text="Key"/> <s:TextInput id="key"/> <s:Label text="Value"/> <s:TextInput id="value"/> <s:Button label="Share" click="shareData()"/> </s:HGroup> <s:HGroup width="100%" verticalAlign="middle"> <s:Label text="New Share Data"/> <s:Label text="Key"/> <s:TextInput id="nKey"/> <s:Label text="Value"/> <s:TextInput id="nValue"/> </s:HGroup> <s:HGroup width="100%" verticalAlign="middle"> <s:Label text="Key"/> <s:TextInput id="fKey"/> <s:Button label="Fetch by Key" click="fetchByKey()"/> <s:Label text="Value"/> <s:TextInput id="fValue"/> </s:HGroup> <s:VGroup width="100%" height="100%" verticalAlign="middle" horizontalAlign="center"> <s:Button label="Fetch All" click="fetchAll()"/> <s:TextArea id="allValue" width="100%" height="100%"/> </s:VGroup> </s:VGroup> </viewer:WidgetTemplate> </viewer:BaseWidget> |
① 在Widget的creationComplete事件的响应方法中,通过ViewerContainer对DATA_SENT和DATA_NEW_PUBLISHED事件进行监听。
② DATA_SENT事件的响应方法,DataManager在两种情况下派发DATA_SENT事件,一是获取所有的共享数据,二是通过key获取共享数据。所以在此实现方法中要对这两种数据区别对待,如果返回的数据是Hashtable类型,则返回的是所有的共享数据,否则返回的是根据key获取的共享数据。
③ DATA_NEW_PUBLISHED事件的响应方法,获取的是最新被共享的数据。DataManager会把最新被共享的数据分发出来(我们已经对DataManager的addData()方法进行了修改,以期达到这个目的)。
④ 调用addShareData()方法共享数据。
⑤ 调用fetchShareDataByKey()方法通过key获取共享数据。
⑥ 调用fetchShareData()方法获取所有的共享数据。
HelloDataManagerWidget运行时如下图所示:
u 点击Share按钮:共享key-value数据,同时最新的共享数据会在New Share Data中显示出来;
u 点击Fetch by Key按钮:根据key获取value;
u 点击Fetch All按钮:获取所有的共享数据。
数据共享机制为业务系统开发提供了很大的方便,比如当一个Widget第一次打开时,需要之前的一些数据进行运算,此时即可通过共享机制实现。