FlexViewer入门资料
轉(zhuǎn)自:http://blog.csdn.net/zhangchuanguo99/article/details/6324998?
1 Sample Flex Viewe架構(gòu)
1.1?架構(gòu)介紹
Sample Flex Viewer框架的構(gòu)建有助于開發(fā)和部署針對(duì)GeoWeb的應(yīng)用程序,使得能夠充分的發(fā)揮服務(wù)器端的空間服務(wù)的能力。服務(wù)器端的服務(wù)通過ArcGIS服務(wù)器和ArcGIS在線數(shù)據(jù)提供。如下圖所示,地球空間信息服務(wù)可以由工作在軟件即服務(wù)方式的伺服機(jī)提供商獲得,比如ArcGIS在線數(shù)據(jù)庫(kù),ArcGIS服務(wù)器或者是像GeoRSS反饋,KML文件庫(kù)以及JSON/REST數(shù)據(jù)等網(wǎng)絡(luò)數(shù)據(jù)源。基于Sample Flex Viewer框架開發(fā)的應(yīng)用程序所消耗的數(shù)據(jù)可以由服務(wù)器端提供,也可以是從移動(dòng)設(shè)備運(yùn)行動(dòng)態(tài)生成的數(shù)據(jù),如現(xiàn)場(chǎng)項(xiàng)目師的筆記本電腦或智能手機(jī)。
?
圖1??地球空間信息服務(wù)
1.2 Sample Flex Viewer實(shí)例的生命周期
一個(gè)Sample Flex Viewer框架的實(shí)例從開始應(yīng)用程序的設(shè)計(jì)到用戶看到帶微件的界面經(jīng)歷了一個(gè)簡(jiǎn)單的生命周期。期間主要的5個(gè)事件如下:1.Flash播放器從加載和運(yùn)行容器文件開始一個(gè)Sample Flex Viewer框架的應(yīng)用程序。2.這個(gè)Flex Viewer容器再?gòu)木W(wǎng)絡(luò)服務(wù)器加載XML格式的配置文件和皮膚文件并應(yīng)用于整個(gè)應(yīng)用程序。3.在配置文件的基礎(chǔ)上,Flex Viewer容器會(huì)從ArcGIS在線數(shù)據(jù)和ArcGIS9.3服務(wù)器下載相關(guān)的地圖信息,然后會(huì)從配置文件中加載并且在控制條上顯示菜單和來自配置文件的標(biāo)記信息。?4.Flex Viewer容器的微件管理器會(huì)從XML配置文件指定的URLs下載并加載相關(guān)的微件文件(一般是swf文件)。?5.用戶利用微件來實(shí)現(xiàn)各種業(yè)務(wù)邏輯。
1.3 Sample Flex Viewer容器
Sample Flex Viewer容器使設(shè)計(jì)人員能夠擺脫地圖管理、地圖導(dǎo)航、應(yīng)用配置、組件間的通信、數(shù)據(jù)管理等繁重復(fù)雜的編程工作,專注于核心業(yè)務(wù)功能開發(fā),尤其是那些利用ERSI公司的ArcGIS技術(shù)的網(wǎng)絡(luò)應(yīng)用開發(fā)人員。而且只需要在Flex Viewer應(yīng)用程序的配置文件中增加配置項(xiàng),就可以將功能以widget的形式快速部署到已有的Flex Viewer應(yīng)用中。Sample Flex Viewer容器由一系列高內(nèi)聚、低耦合組件組成(如下圖所示)。容器會(huì)把關(guān)注的任務(wù)交給相應(yīng)的組件去完成。這種設(shè)計(jì)方法不但簡(jiǎn)化了代碼維護(hù)和定制,而且縮小了模塊編寫過程中產(chǎn)生的阻力。
?
圖2??Sample Flex Viewer容器整體架構(gòu)
1.4?理解Widget編程模型
經(jīng)過編譯的widget是一個(gè)獨(dú)立的SWF(Flash)文件,可在Flex Viewer程序中共享、移動(dòng)和配置。Widget封裝了一系列獨(dú)立并且針對(duì)性很強(qiáng)的業(yè)務(wù)邏輯,用戶可以在其中執(zhí)行任務(wù)。在一個(gè)面向服務(wù)的環(huán)境下,一個(gè)widget可以代表是一種服務(wù)或者是一套相關(guān)的服務(wù),用戶可以很明了的用它來執(zhí)行一個(gè)業(yè)務(wù)功能。widget不僅為用戶提供了可視化的界面,也能夠連到服務(wù)器端的資源,像是來自ArcGIS服務(wù)器或是ArcGIS在線數(shù)據(jù)庫(kù)的地圖服務(wù)。一系列相互關(guān)聯(lián)的widget加上清晰定義好的業(yè)務(wù)操作流程組成了業(yè)務(wù)解決方案。而且這樣的方案可以應(yīng)用于企業(yè)級(jí)的業(yè)務(wù)進(jìn)程中。輕量級(jí)的Flex Viewer Widget編程模型使得開發(fā)人員可以輕易定制widget,避免了將widget整合到Flex Viewer應(yīng)用程序中所需的底層代碼開發(fā)。widget編程模型包含了兩個(gè)ActionScript類(其中一個(gè)后為mxml類)以及兩個(gè)ActionScript接口。后面一個(gè)章節(jié)將會(huì)講述如何使用這些類以及接口的相關(guān)細(xì)節(jié)。
IBaseWidget Interface (IBaseWidget.as)?這個(gè)接口定義了WidgetManager管理微件的通信方法。而基礎(chǔ)widget類BaseWidget則要來實(shí)現(xiàn)這個(gè)接口。
BaseWidget Class (BaseWidget.as)?這個(gè)是widget的基類,所有的微件都要繼承這個(gè)類。通過擴(kuò)展BaseWidget這個(gè)父類,WidgetManager會(huì)驗(yàn)證所有擴(kuò)展了BaseWidget的MXML或AS類是否為可部署的微件。另外,擴(kuò)展了BaseWidget的類能夠被編譯為一個(gè)獨(dú)立的SWF文件。每個(gè)Flex Viewer框架下的微件必須繼承BaseWidget這個(gè)父類。
IWidgetTemplate (IWidgetTemplate.as)?這個(gè)接口定義了widget模板能夠被BaseWidget識(shí)別所需要的一般操作。是使用一個(gè)widget模板還是使用內(nèi)置的widget模板通常是可選的。內(nèi)置的WidgetTemplate類要實(shí)現(xiàn)IWidgetTemplate這個(gè)接口。
WidgetTemplate (WidgetTeamplate.mxml)?這是一個(gè)內(nèi)置的widget模板,它是一個(gè)為widget提供基本的布局和行為的用戶界面組件。這些布局和行為包括一個(gè)標(biāo)準(zhǔn)的窗口面板,帶有自定義圖標(biāo)按鈕的標(biāo)題欄等組件。使用這類模板,使得widget開發(fā)者能夠把更多的時(shí)間和精力放在核心的業(yè)務(wù)需求上面。內(nèi)置的widget模板通常也能被widget開發(fā)者用來定制屬于自己的widget模板,前提是必須實(shí)現(xiàn)IWidgetTemplate這個(gè)接口。
1.5??Widget命名習(xí)慣
Widget?類:?一般來講一個(gè)widget類得有”Widget”這樣一個(gè)后綴,比如”NameWidget.mxml”?;Widget?的配置文件:?一個(gè)好的習(xí)慣就是,將widget的配置文件取相同的文件名,只是擴(kuò)展名采用xml,比如NameWidget.xml。
2?開發(fā)一個(gè)widget
盡管前面兩個(gè)章節(jié)講述了兩種widget項(xiàng)目開發(fā)的途徑,但其實(shí)它們實(shí)際的核心功能開發(fā)的原理是一樣的。這一章我們會(huì)用第一種開發(fā)方式來做更深入的講解。我們先假設(shè)widge的開發(fā)員很熟悉Flex的開發(fā)環(huán)境。
2.1?使用WidgetTemplate模板
在接著2.1節(jié)所創(chuàng)建的一個(gè)widget文件MyFirstWidget.mxml講,它的代碼如下:
| <?xml version="1.0" encoding="utf-8"?> <BaseWidget?xmlns="com.esri.solutions.flexviewer.*"xmlns:mx="http://www.adobe.com/2006/mxml> </BaseWidget> |
在widget編程模型匯中的WidgetTemplate模板提供的默認(rèn)widget窗口給出了一套很豐富的內(nèi)置組件。使用這個(gè)模板添加兩行如下代碼:
| <?xml?version="1.0" encoding="utf-8"?> <BaseWidget xmlns="com.esri.solutions.flexviewer.*"xmlns:mx="http://www.adobe.com/2006/mxml> <WidgetTemplate?id="widgetTempalte"> </WidgetTemplate> </BaseWidget> |
按照如下幾個(gè)步驟進(jìn)行配置和部署就能看到運(yùn)行結(jié)果:
第一步:在config.xml中添加創(chuàng)建的widget;打開config.xml文件添加下面幾行代碼到<widget>標(biāo)記塊,你可以為創(chuàng)建的widget使用自己的圖標(biāo),可以是40×40的一個(gè)png圖像文件,或者gif、jpg文件。
| <widget?label??= "My First Widget" icon???= " com/esri/solutions/flexviewer/assets/images/icons/i_globe.png"menu???= "menuWidgets" config?= "";> mywidgets/MyFirstWidget.swf </widget> |
第二步:保存文件并編譯整個(gè)項(xiàng)目;具體編譯方法參考上一章內(nèi)容。
第三步:運(yùn)Flex Viewer應(yīng)用程序;右鍵項(xiàng)目中的index.mxml文件并點(diǎn)擊Run Application。
第四步:從工具菜單,點(diǎn)擊MyFirstWidget;
下面將會(huì)加載并輸出顯示你的widget。
?
圖3??My First Widget菜單
前面給widget添加的兩行代碼,是的當(dāng)前的widget能夠有一個(gè)標(biāo)準(zhǔn)的視圖和感官效果,并且能夠有一些基本功能,比如能夠最小化,最大化以及關(guān)閉的效果。而且,當(dāng)前的widget還可以和Sample Flex Viewer進(jìn)行內(nèi)部通信。接下來就可以在WidgetTemplate模板上添加自己的UI元素并且寫自己的業(yè)務(wù)邏輯了。
2.2?獲取地圖信息
Sample Flex Viewer是一個(gè)基于地圖服務(wù)開發(fā)的應(yīng)用。一旦這個(gè)應(yīng)用被初始化,通常widget能夠從ArcGIS的地圖服務(wù)上連接到一個(gè)或者多個(gè)地圖資源。在基類BaseWidget中定義了一個(gè)公共屬性map,一個(gè)widget被加載以后widget管理器就會(huì)把當(dāng)前激活的一個(gè)地圖對(duì)象傳給這個(gè)widget。這個(gè)widget的map屬性來自com.eari.ags.Map類,繼承于ArcGIS API for Flex。你就能夠訪問到ArcGIS提供的所有的地圖參數(shù)。widget的代碼寫起來就像一個(gè)常規(guī)的ArcGIS Flex的應(yīng)用程序一樣。這里有一個(gè)例子,在MyFirstWidget中添加了一個(gè)按鈕。當(dāng)點(diǎn)擊這個(gè)按鈕時(shí),地圖就會(huì)自動(dòng)的以當(dāng)前設(shè)置的坐標(biāo)為中心。在編譯并且配置完widget后重新運(yùn)行Sample Flex Viewer應(yīng)用程序,如圖:
?
圖4??My First Widget微件圖
2.3?在地圖上顯示widget數(shù)據(jù)
添加圖層
建議為每一個(gè)新創(chuàng)建的widget添加一個(gè)圖層,這個(gè)圖層能夠被添加到地圖服務(wù)中去,具體是在widgetConfigLoaded這個(gè)事件處理器中的init方法進(jìn)行相關(guān)初始化操作。當(dāng)所有的widget的配置信息加載完畢并且待命時(shí)就會(huì)傳出一個(gè)widgetConfigLoaded事件。相應(yīng)代碼如下:
| <?xml?version="1.0" encoding="utf-8"?> <BaseWidget?x="600" y="300" xmlns:esri="http://www.esri.com/2008/ags" xmlns="com.esri.solutions.flexviewer.*"xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:mxeffects="com.adobe.ac.mxeffects.*" xmlns:widgets="com.esri.solutions.flexviewer.widgets.*"widgetConfigLoaded="init()"?> <mx:Script> <![CDATA[ … ? private?function?init():void { graphicPointSym?=?new?PictureMarkerSymbol(widgetIcon, 30, 30) graphicsLayer =?newGraphicsLayer();?graphicsLayer.symbol= graphicPointSym;map.addLayer(graphicsLayer); ? … |
一旦添加了圖層,你接下來就能使用標(biāo)準(zhǔn)的ArcGIS API for Flex中的各個(gè)方法來給圖層加上各種圖形元素。當(dāng)點(diǎn)擊open/minimize的圖標(biāo)時(shí)打開/關(guān)閉widget圖層。WidgetTemplate模板設(shè)置了兩個(gè)窗口狀態(tài)事件:widgetOpened以及widgetClosed事件。他們都是擴(kuò)展于flash.events.Event這個(gè)類。你可以使用這兩個(gè)事件來同步同步圖層的可見性。在這個(gè)例子里,我們先添加兩個(gè)事件處理器到WidgetTemplate模板:
| <WidgetTemplate?id="wTemplate"widgetClosed="widgetClosedHandler(event)"widgetOpened="widgetOpenedHandler(event)"> private?function?widgetClosedHandler(event:Event):void { graphicsLayer.visible?=?false; } ? ? private?function?widgetOpenedHandler(event:Event):void { graphicsLayer.visible?=?true; } |
2.4?從地圖接收數(shù)據(jù)(通過單擊,畫線等操作實(shí)現(xiàn))
對(duì)于GIS網(wǎng)絡(luò)應(yīng)用,除了可視化數(shù)據(jù)這個(gè)特殊用途外,地圖還是一個(gè)允許用戶收集并且處理地圖數(shù)據(jù)的數(shù)據(jù)源。或許在用戶與地圖進(jìn)行交互的過程中,我們創(chuàng)建的widget需要接收如點(diǎn)和直線或多邊形這一類的數(shù)據(jù)來進(jìn)行處理。那么Sample Flex Viewer以及widget編程模型就能夠用微件通過內(nèi)置的setMapAction方法來請(qǐng)求或是接收這一類的地圖數(shù)據(jù)。下面這段代碼展示了如何激活畫圖工具來追蹤用戶在地圖上面的點(diǎn)擊操作:
?
| private?function?activateTool():void { setMapAction(Draw.POINT,?"Click Point",?drawEnd); } private?function?drawEnd(event:DrawEvent):void { var?geom:Geometry = event.geometry; var?pt:MapPoint = geom?as?MapPoint Alert.show("Click location: "?+ pt.x +?", "?+ pt.y); } |
在上面的示例中,點(diǎn)擊widget中的按鈕會(huì)調(diào)用activeTool()方法。當(dāng)一個(gè)指定的任務(wù)需要用戶點(diǎn)擊widget上的按鈕時(shí),程序就能夠隨時(shí)從地圖上獲取一個(gè)點(diǎn)的坐標(biāo)信息。用戶下一步需要做的就是點(diǎn)擊地圖上任意位置,然后widget就能夠接收這個(gè)點(diǎn)擊行為傳送的點(diǎn)信息。具體由一個(gè)回調(diào)函數(shù)drawEnd()傳回參數(shù)到setMapAction()方法來實(shí)現(xiàn)具體操作。
setMapAction方法
公共方法setMapAcion定義在BaseWidget類里(在BaseWidget.as文件中),這樣所有繼承該類的widget就能夠自動(dòng)繼承這個(gè)特性。該方法定義如下:public function setMapAction(action:String, status:String, callback:Function):void,其中參數(shù):
action:?這個(gè)字符串標(biāo)記表示ArcGIS API相應(yīng)的畫圖工具被激活。下面列出的是ArcGIS Flex API提供的能夠用來訪問各種畫圖工具的字符串標(biāo)記:
extent???(Draw.EXTENT) point???(Draw.MAPPOINT) line??(Draw.LINE) polyline???????(Draw.POLYLINE) polygon?(Draw.POLYGON)
multipoint????(Draw.MULTIPOINT)
freehandpolyline???????(Draw.FREEHAND_POLYLINE)
freehandpolygon???????(Draw.FREEHAND_POLYGON)
status:在控制條的狀態(tài)欄顯示的文本文字;
callback:畫圖操作完成后Map Manager回調(diào)的函數(shù)。
2.5?在widget中控制導(dǎo)航
當(dāng)開發(fā)一個(gè)widget時(shí),為了能夠全屏顯示,放大或是縮小地圖,往往在用例中會(huì)需要控制地圖的導(dǎo)航。比如,當(dāng)一個(gè)widget被關(guān)閉后,你需要關(guān)閉相應(yīng)的圖層,并且使得地圖處于默認(rèn)的全屏狀態(tài)。BaseWidget類提供了一個(gè)public方法setMapNavigation用來進(jìn)行這些操作。代碼如下:
| <WidgetTemplate?id="wTemplate" widgetClosed="widgetClosedHandler(event)"… private?function?widgetClosedHandler(event:Event):void { graphicsLayer.visible?=?false; setMapNavigation(Navigation.PAN,?“Pan Map”); } |
在上面的代碼里,我們給WidgetTemplate這個(gè)模板一個(gè)事件處理器來相應(yīng)widget關(guān)閉這個(gè)事件。在widgetClosedHandle處理器內(nèi)部,public方法setMapNavigation被調(diào)用來將地圖的導(dǎo)航顯示為全屏狀態(tài)。
setMapNavigation方法在BaseWidget中setMapNavigation定義如下:public function setMapNavigation(navMethod:String, status:String):void,其中參數(shù):
navMethod:地圖導(dǎo)航的標(biāo)記列表如下:(定義了Flex API類中的導(dǎo)航或者Sample Flex Viewer類的SiteContainer容器)
pan?(Navigation.PAN) zoomin(Navigation.ZOOM_IN)
zoomout(Navigation.ZOOM_OUT)
zoomfull(SiteContainer.NAVIGATION_ZOOM_FULL)
zoomprevious(SiteContainer.NAVIGATION_ZOOM_PREVIOUS)
zoomnext?????(SiteContainer.NAVIGATION_ZOOM_NEXT)
status:?在控制條的狀態(tài)欄顯示的文本文字
2.6?不使用WidgetTemplate模板開發(fā)Widget
開發(fā)widget并不一定會(huì)用到WidgetTemplate這個(gè)模板,再有的情況下,widget模板的窗口并不一定是必要的。比如,或許在你的應(yīng)用程序中需要用一個(gè)與時(shí)鐘相關(guān)的widget來顯示當(dāng)前的時(shí)間。這個(gè)時(shí)鐘并不需要一個(gè)window框架,其代碼如下:
| <BaseWidget?xmlns="com.esri.solutions.flexviewer.*"xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:SWFLoader?source="mywidgets/clock.swf"/> ? </BaseWidget> |
在上面的代碼中,我們使用一個(gè)SWFLoader來加載外部的flash文件到要開發(fā)?的widget中。然而,在這個(gè)時(shí)鐘微件中,會(huì)發(fā)現(xiàn)WidgetTemplate模板所提供的很多有用的特性我們根本沒用到。所以,作為widget的開發(fā)員要有這樣一個(gè)共識(shí),那就是隨時(shí)需要自己寫代碼來增加開發(fā)widget時(shí)所想到,而不是僅僅依賴既有模板所提供的那些特性。
2.7?開發(fā)一個(gè)自己的Widget模板
Widge編程模型允許開發(fā)者創(chuàng)建自己的widget模板。當(dāng)然,新的widget模板類也需要實(shí)現(xiàn)iWidgetTemplate這個(gè)模板接口,因?yàn)樗荁aseWidget類與widget的模板之間進(jìn)行交互的核心接口。實(shí)現(xiàn)一個(gè)接口就意味著里面所有的方法都必須得以實(shí)現(xiàn)。這樣,新的widget模板類需要實(shí)現(xiàn)iWidgetTemplate接口中的setTitle,setIcon和setState這三個(gè)方法。下面說明如何創(chuàng)建一個(gè)基于Flex組件TitleWindow的widget模板MyTemplate:
| <?xml?version="1.0" encoding="utf-8"?> <mx:TitleWindow?xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="300"implements="com.esri.solutions.flexviewer.IWidgetTemplate"> <mx:Script> <![CDATA[ public?function?setTitle(value:String):void { this.title = value; } public?function?setIcon(value:String):void{ } public?function?setState(value:String):void{ } ]]> </mx:Script> </mx:TitleWindow> |
接下來向MyTemplate組件中添加一些代碼,上面展示的只是一個(gè)最簡(jiǎn)單的widget模板,它能夠接收widget的標(biāo)題,圖標(biāo)并在TitleWindow組件中進(jìn)行配置。下一步我們?cè)趍ywidgets空間(文件夾)下創(chuàng)建一個(gè)新的widget并,命名為MyTempWidget,使用我們自己的模板,然后在其中添加一個(gè)按鈕。
| <?xml?version="1.0" encoding="utf-8"?> <BaseWidget xmlns="com.esri.solutions.flexviewer.*"xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:mywidgets="mywidgets.*"> <mywidgets:MyTemplate> <mx:Button?label="Hello, World!"/> </mywidgets:MyTemplate> </BaseWidget> |
2.8?修改或創(chuàng)建一個(gè)主題
Sample Flex Viewer應(yīng)用程序的整體觀感都能夠自定義或是根據(jù)需要進(jìn)行修改。這個(gè)主題(或者叫做‘皮膚’)它跟我們編程代碼是分開的。內(nèi)置的主題名字叫做DarkAngle。DarkAngle皮膚是使用web上標(biāo)準(zhǔn)的層疊樣式列表文件com/esri/solutions/flexviewer/themes/darkangel/style.css進(jìn)行構(gòu)建的。這個(gè)CSS文件也能被編譯成一個(gè)獨(dú)立的主題文件,一個(gè)SWF。它在運(yùn)行時(shí)被從配置文件config.xml所指定的位置加載到應(yīng)用程序中。在config.xml配置文件中stylesheet標(biāo)簽用來提供主題的swf文件的URL地址共應(yīng)用程序訪問。注意:?對(duì)Sample Flex Viewer應(yīng)用程序作的修改會(huì)在運(yùn)行時(shí)自動(dòng)的應(yīng)用到各個(gè)微件。下面的步驟說明如何新建一個(gè)自己的主題:
第一步:修改DarkAngle的css文件或者新建一個(gè)css文件;新建css文件的話要遵循css標(biāo)準(zhǔn),可以參考Flex開發(fā)文檔。
第二步?:改變或者是替換原有圖標(biāo):在css文件中有一些使用到內(nèi)置圖標(biāo)的圖像文件元素,你可以修改這些css文件中對(duì)于的圖標(biāo)。
第三步:編譯css文件到swf文件中;這一步很重要只有編譯到swf文件才能被Sample Flex Viewer應(yīng)用在運(yùn)行時(shí)所識(shí)別和加載。要編譯這個(gè)css文件,只需要右鍵之并從彈出菜單選擇Compile CSS to SWF?命令。選擇了這個(gè)命令以后,下次build這個(gè)Flex Viewer項(xiàng)目時(shí)css文件會(huì)被自動(dòng)編譯到一個(gè)獨(dú)立的swf文件中去。為了能夠重新生成主題文件,你可以再編譯一下當(dāng)前的項(xiàng)目。
第四步:添加新建主題文件的URL到config.xml配置文件。要使用新建的主題文件,只需要修改config.xml中的stylesheet標(biāo)簽,指定到編譯好的swf主題文件位置。
2.9 Widget配置
通過設(shè)計(jì)每個(gè)widget能夠產(chǎn)生自己的配置文件,這些配置文件的位置在Sample Flex Viewer里config.xml相應(yīng)的widget標(biāo)記對(duì)中指定。widge編程模型只支持xml格式的配置文件。WidgetManager會(huì)把widget配置文件的URL傳給BaseWidget。BaseWidget會(huì)加載并分析這個(gè)xml格式的配置文件,然后在該文件的actionScript代碼段中設(shè)置一個(gè)public的屬性configXML傳遞配置參數(shù)。當(dāng)widget創(chuàng)建完成后可以在自己的widget代碼中訪問到configXML這個(gè)屬性。即使盒外開發(fā)的Viewer只支持xml格式的配置文件,你也可用自己的配置文件來格式化widget代碼。這些配置文件會(huì)被Flex的HTTPservice服務(wù)連接并加載。在加載和分析其他格式的配置數(shù)據(jù)時(shí)也能使用相同的方法。
3?了解Sample Flex Viewer核心代碼
Sample Flex Viewer源代碼對(duì)公眾免費(fèi)開放,而且在自定義和擴(kuò)展Viewer的核心功能方面沒有任何限制。具體限制參考發(fā)布包中許可文件。Flex Viewer的設(shè)計(jì)是為了使開發(fā)者在擴(kuò)展時(shí)更方便。通過Container Event Bus以及利用依賴注入這兩種設(shè)計(jì)方法可以實(shí)現(xiàn)高內(nèi)聚和低耦合。在自定義Sample Flex Viewer的內(nèi)核時(shí),這兩張方法很重要。
3.1?事件總線容器
Event Bus容器是一個(gè)全局的時(shí)間發(fā)布器,它是用來促進(jìn)不同組件直接的交互(或者說信息傳遞)。事件總線容器在EventBus這個(gè)類(存在于EventBus.as文件)中定義,在SiteContainer類(存在于SiteContainer.mxml文件)中定義的一組靜態(tài)代理方法保證了能夠順利訪問event bus容器。下表說明了Configmanager如何加載配置并通過事件容器將其應(yīng)用到其他組件的。當(dāng)Configmanager被初始化以后,它就開始監(jiān)聽事件,如圖:
| public?function?ConfigManager() { super(); //make sure the container is properly initialized and then //proceed with configuration initialization. ? SiteContainer.addEventListener(SiteContainer.CONTAINER_INITIALIZED, init); } |
在上面的代碼中,定義的inti()函數(shù)是一個(gè)接收到事件后會(huì)開始加載配置數(shù)據(jù)的事件處理器。其中addEventListener方法又是一個(gè)用來訪問事件總線的代理方法。
?
圖5??Flex Viewer中Container組件的架構(gòu)
當(dāng)事件總線容器加載完畢以后SiteContainer容器就會(huì)發(fā)布CONTAINER_INITIALIZED?事件,具體參照以下代碼:
| public?function?init():void { _container =?this; _lock =?true;?//make sure only one container is created. initLogging();//make sure the event bus is ready. _containerEventDispatcher = EventBus.getInstance(); //tell the modules it's on business. SiteContainer.dispatch(SiteContainer.CONTAINER_INITIALIZED); } |
在SiteContainer類中,如上所示,一旦被初始化,就會(huì)發(fā)布CONTAINER_INITIALIZED事件。通過使用發(fā)布信息方法,組件之間可以在無需其他方法和數(shù)據(jù)的直接干預(yù)下進(jìn)行監(jiān)護(hù)。最終這些組件就通過這些基于事件的消息達(dá)到了去耦和分離的效果。這樣的話,只要組件之間的消息能夠同步,那么任何組件的修改都不會(huì)直接影響到其他組件。
| public?function?init(event:Event):void { ???configLoad(); } //config load private?function?configLoad():void { ???var configService:HTTPService = new HTTPService(); ???configService.url = "config.xml"; ???configService.resultFormat = "e4x"; ???configService.addEventListener(ResultEvent.RESULT, configResult); ???configService.addEventListener(FaultEvent.FAULT, configFault); ???configService.send(); } //config result private?function?configResult(event:ResultEvent):void { ???try ???{?? ????//parse config.xml to create config data object ??????var configData:ConfigData = new ConfigData(); ??????………… ??????//dispatch event ???SiteContainer.dispatchEvent(new????????????????????AppEvent(AppEvent.CONFIG_LOADED,?false,?false,?configData)); } |
在上面的表格中,一旦ConfigManager完成了對(duì)配置文件的分析,它就會(huì)發(fā)布一個(gè)帶有配置信息的數(shù)據(jù),而所有需要配置信息數(shù)據(jù)的組件,比如WidgetManager以及MapManager,只需要簡(jiǎn)單的接收這個(gè)事件發(fā)布的數(shù)據(jù)。
| private?function?init():void { ? SiteContainer.addEventListener(AppEvent.CONFIG_LOADED, config); … } |
這個(gè)通過事件總線發(fā)布消息的方法可以在Sample Flex Viewer的核心代碼中找到。你也可以用相同的方法來添加組件或是改變組件之間交互的方式。
3.2?依賴注入(DI)
依賴注入在通常的電腦編程中指的是向一個(gè)軟件中的組件添加一個(gè)外部依賴的過程。應(yīng)用控制反轉(zhuǎn),對(duì)象在被創(chuàng)建的時(shí)候,由一個(gè)調(diào)控系統(tǒng)內(nèi)所有對(duì)象的外界實(shí)體,將其所依賴的對(duì)象的引用,傳遞給它。也可以說,依賴被注入到對(duì)象中。所以,控制反轉(zhuǎn)是,關(guān)于一個(gè)對(duì)象如何獲取他所依賴的對(duì)象的引用,這個(gè)責(zé)任的反轉(zhuǎn)。
一般情況下,如果一個(gè)對(duì)象獲取了某一個(gè)服務(wù)資源,這個(gè)對(duì)象就有責(zé)任掛載這個(gè)服務(wù):要么是直接掛載這個(gè)服務(wù)所在位置的一個(gè)依賴關(guān)系,要么轉(zhuǎn)到所謂的“服務(wù)查詢器”并請(qǐng)求它傳回一個(gè)特定類型服務(wù)實(shí)現(xiàn)的依賴。相反,如果使用依賴注入,這個(gè)對(duì)象只需要簡(jiǎn)單的提供一個(gè)能夠掛載住該特定類型服務(wù)依賴的屬性即可;當(dāng)這個(gè)對(duì)象被創(chuàng)建時(shí),外部機(jī)制就會(huì)自動(dòng)生成一個(gè)實(shí)現(xiàn)了該類型服務(wù)的依賴的屬性。這種依賴注入的方式提供了更好的靈活性,因?yàn)槭沟脛?chuàng)建給定服務(wù)類型的實(shí)現(xiàn)并將其應(yīng)用于配置文件而不需要改變使用該類型服務(wù)的對(duì)象這個(gè)過程變得更加簡(jiǎn)單。在Sample Flex Viewer中,這個(gè)過程體現(xiàn)在創(chuàng)建widget中,DI同樣能夠被用來創(chuàng)建自定義的widget模板。
下面的代碼介紹了WidgetManager是如何運(yùn)用依賴注入在不需要知道widget的具體實(shí)現(xiàn)的情況下加載相應(yīng)widget到容器的:
| private?function?widgetReadyHandler(event:ModuleEvent):void { var?info:IModuleInfo = event.module; moduleTable.add(info.url, info); var?id:Number = info.data.id; var?label:String = configData.configWidgets[id].label; var?icon:String = configData.configWidgets[id].icon; var?config:String = configData.configWidgets[id].config; var widget:IBaseWidget = info.factory.create() as IBaseWidget; widget.setId(id); widget.setTitle(label); widget.setIcon(icon); widget.setConfig(config); widget.setConfigData(configData); widget.setMap(map); widgetTable.add(id, widget); var?widgetDO:DisplayObject = widget?as?DisplayObject; addChild(widgetDO); this.cursorManager.removeBusyCursor(); } |
在上面代碼中,一旦widget模塊被加載,他就會(huì)轉(zhuǎn)變成IbaseWidget接口類型。而BaseWidget在這個(gè)Di應(yīng)用中是需要擴(kuò)展IbaseWidget接口的,這樣WidgetManager就不需要知道所操作的widget是那種類型或是具有哪些功能。WidgetManager只需要調(diào)用IbaseWidget中定義的各個(gè)方法來和已加載的widget進(jìn)行交互。由此,實(shí)現(xiàn)widget的時(shí)候就不用關(guān)心它可能會(huì)有多么的復(fù)雜,而且這個(gè)實(shí)現(xiàn)的過程跟WidgetManager乃至整個(gè)Flex Viewer容器是完全分離開的。在這種情況下,開發(fā)員就能夠相對(duì)自由地開發(fā)自己的widget而不受Flex Viewer框架的限制了。建議在開發(fā)自定義的Sample Flex Viewer核心功能時(shí)最好通過使用DI來保持這種開發(fā)widget的靈活性。這樣做可以通過添加微件而不是修改核心功能的特性來增加功能的一致性。這種方法可以使得你開發(fā)的程序比別人簡(jiǎn)單許多,而且一定程度上避免了在添加功能特性操作的復(fù)雜性。
3.3?國(guó)際化
國(guó)際化(aka i18n)和本地化(aka l10n)有很多不同之處。國(guó)際化(internationalization)是設(shè)計(jì)和制造容易適應(yīng)不同區(qū)域要求的產(chǎn)品的一種方式。它要求從產(chǎn)品中抽離所有的與語(yǔ)言,國(guó)家/地區(qū)和文化相關(guān)的元素。換言之,應(yīng)用程序的功能和代碼設(shè)計(jì)考慮在不同地區(qū)運(yùn)行的需要,其代碼簡(jiǎn)化了不同本地版本的生產(chǎn)。開發(fā)這樣的程序的過程,就稱為國(guó)際化。國(guó)際化根據(jù)用戶的需求不同,通常支持多種語(yǔ)言的選擇;而本地化通常是針對(duì)區(qū)域語(yǔ)言。由于跟國(guó)際化所依賴的語(yǔ)言元素不同,它們的設(shè)計(jì)方法也有所區(qū)別。
鑒于Sample Flex Viewer并不是最終設(shè)計(jì)和開發(fā)的成品,它以在代碼中以示例的形式支持國(guó)際化和本地化,而并沒有將其統(tǒng)一化。
3.3.1?使用Flex的國(guó)際化特性
對(duì)于Flex如何支撐國(guó)際化的具體細(xì)節(jié),請(qǐng)參考Flex軟件開發(fā)工具包(SDK)文檔。在Sample Flex Viewer項(xiàng)目中創(chuàng)建了一個(gè)子文件夾nls來承載國(guó)際化的所有文本字符。比如,這里提供了有兩種語(yǔ)言en_US(美式英語(yǔ))和fr_FR(法語(yǔ))。下面介紹配置Flex Builder使其支持國(guó)際化的步驟:
第一步:從項(xiàng)目屬性中添加編譯器選項(xiàng);
第二步:把國(guó)際化的目錄路徑添加到Build Source;路徑中的{locale}允許編譯器根據(jù)步驟一中的編譯選項(xiàng)進(jìn)行操作。
第三步:為語(yǔ)言創(chuàng)建資源文件;比如說,我們?cè)趎ls文件夾下的en_US以及fr_FR子文件夾中創(chuàng)建了一個(gè)資源文件WidgetTemplateStrings.properties然后Flex的編譯器能夠自動(dòng)識(shí)別到擴(kuò)展名properties。資源文件中的語(yǔ)言文本字符定義很簡(jiǎn)單;
第四步:在代碼中使用國(guó)際化。比如在WidgetTemplate.mxml中使用國(guó)際化資源,需要先定義綁定到指定資源文件的資源綁定。
| <mx:Metadata>[ResourceBundle("WidgetTemplateStrings")] </mx:Metadata> |
然后創(chuàng)建一個(gè)nlsString方法來檢索指定語(yǔ)言的字符串。
| private?function?nlsString(nlsToken:String):String { return?resourceManager.getString('WidgetFrameStrings', nlsToken); } addTitlebarButton("com/esri/solutions/flexviewer/assets/images/ widget/w_delete.png",nlsString("close"), closeWidget); addTitlebarButton("com/esri/solutions/flexviewer/assets/images/ widget/w_min.png", nlsString("minimize"), minimizeWidget); |
3.3.2?本地化設(shè)置
作為一個(gè)可選方法,使用配置文件來使得標(biāo)簽字符本地化還是很簡(jiǎn)便的。Sample Flex Viewer中內(nèi)置的widget?比如LiveMapsWidget就是個(gè)很好的例子。在這個(gè)widget種,標(biāo)簽字符都被定義在widget的配置文件LiveMapsWidget.xml中。在這種情況下,如果想覆蓋默認(rèn)語(yǔ)言設(shè)置的話,只需要編輯配置文件中的代碼即可。
| <configuration> <labels> <visibilitylabel>Layer Visibility</visibilitylabel> <transparencylabel>Layer Transparency</transparencylabel> </labels> </configuration> |
3.4?日志和錯(cuò)誤處理
日志和錯(cuò)誤處理功能的結(jié)合有助于開發(fā)功能文檔和高質(zhì)量的軟件。
日志處理
在ActionScript和Flex的應(yīng)用程序的日志記錄中常常有很多可用的選項(xiàng)和工具。比如,我們?cè)赟iteContainer中設(shè)置了一個(gè)日志文件來記錄遠(yuǎn)過程調(diào)用協(xié)議(RPC)和基于基于網(wǎng)絡(luò)信息傳輸過程中的錯(cuò)誤信息。HTTP連接是一類RPC連接,它記錄日志文件的代碼如下:
| private?function?initLogging():void?{ // Create a target. var?logTarget:TraceTarget =?new?TraceTarget(); // Log only messages for the classes in the mx.rpc.* and // mx.messaging packages. logTarget.filters=["mx.rpc.*","mx.messaging.*"]; // Log on fatal levels. logTarget.level = LogEventLevel.FATAL; // Add date, time, category, and log level to the output. logTarget.includeDate???????=true; logTarget.includeTime???????=true; logTarget.includeCatego?=true; logTarget.includeLevel??=true;// Begin logging. Log.addTarget(logTarget); } |
這里用的是基于Flex的日志結(jié)構(gòu)。更多詳細(xì)信息可用參考Flex文檔。
錯(cuò)誤處理
ActionScript3提供了強(qiáng)大的堪比Java的錯(cuò)誤處理機(jī)制。然而,相應(yīng)的編譯器卻不能夠如后者一樣去預(yù)測(cè)潛在的錯(cuò)誤和異常。所以,Flex或者說ActionScript的程序員就要自己使用錯(cuò)誤事件處理器和try-catch異常捕獲功能來捕獲和處理編程過程中遇到的各種問題。最好的建議是:實(shí)現(xiàn)所有可能想到的錯(cuò)誤事件;?盡量嘗試使用try-catch異常捕獲功能。
一旦發(fā)現(xiàn)錯(cuò)誤,最好用直白易懂的語(yǔ)言去做標(biāo)注并解釋錯(cuò)誤情況。Sample Flex Viewer提供了一個(gè)簡(jiǎn)單的錯(cuò)誤顯示功能并能夠方便地發(fā)送和提示相應(yīng)的錯(cuò)誤信息。對(duì)于一個(gè)widget?,定義在BaseWidget中的一個(gè)public方法showError()能夠用來實(shí)現(xiàn)這一功能,例如:
showError("This is a <b>test</b> error message!");
這段代碼用來返回Sample Flex Viewer應(yīng)用程序中出現(xiàn)的錯(cuò)誤。注意到這段錯(cuò)誤信息窗口只是一個(gè)形式,里面的文本可以使用基本的Html標(biāo)記進(jìn)行必要的設(shè)計(jì)。在后臺(tái),這個(gè)錯(cuò)誤信息是通過前面一章講到過對(duì)的事件總線來進(jìn)行傳遞的。換言之,錯(cuò)誤信息能夠在Flex Viewer或者一個(gè)widget中根據(jù)需要任意傳播。
| SiteContainer.dispatchEvent(newAppEvent(AppEvent.APP_ERROR, false, false, “the error message string”)); |
4 Sample Flex Viewer框架和Widget部署
4.1?部署一個(gè)Sample Flex Viewer應(yīng)用程序
如果你已經(jīng)下載了Sample Flex Viewer的發(fā)布包,那么只需要簡(jiǎn)單的解壓該zip文件到一個(gè)能夠訪問到網(wǎng)絡(luò)服務(wù)器的文件系統(tǒng)下面即可完成部署。也可能需要配置一下網(wǎng)絡(luò)服務(wù)器是的加載這個(gè)文件系統(tǒng)時(shí)輸入的URL更簡(jiǎn)潔。比如在第2.3節(jié)中講到過,可以創(chuàng)建一個(gè)IIS的虛擬目錄,這一塊的部署跟其他Html的網(wǎng)絡(luò)應(yīng)用程序部署方法基本相同。
部署自己編譯的Sample Flex Viewer?應(yīng)用
如果你想使用自己編譯的代碼來部署Sample Flex Viewer應(yīng)用程序,建議多做一步,就是用到Project菜單下的Export Release Build命令。因?yàn)槿コ讼鄳?yīng)的debug信息,到處的swf文件往往會(huì)更小。最終,這個(gè)應(yīng)用比Debug后創(chuàng)建的程序更好用。默認(rèn)情況下,Flex會(huì)創(chuàng)建一個(gè)新的文件夾bin-release來放置相關(guān)的發(fā)布文件。而這個(gè)文件夾里面的所有文件都可以是你的發(fā)布包中的內(nèi)容。也就意味著你可以對(duì)它重新命名,把它打包并部署到特定的網(wǎng)絡(luò)應(yīng)用中去。
4.2?部署一個(gè)widget到Sample Flex Viewer
假設(shè)一個(gè)Sample Flex Viewer的應(yīng)用已經(jīng)部署并且也已開發(fā)好了一個(gè)widget,那么下面說明如何配置這個(gè)widget:
第一步:把widget的swf文件復(fù)制到特定的文件位置;一個(gè)widge是一個(gè)獨(dú)立于外部的swf文件,你可以把該swf文件拷到Sample Flex Viewer應(yīng)用的網(wǎng)絡(luò)服務(wù)器能夠訪問到的位置或者直接拷到另外一個(gè)網(wǎng)絡(luò)服務(wù)器上。
第二步:修改?Sample Flex Viewer應(yīng)用的配置文件;配置文件config.xml在該應(yīng)用程序的根文件夾下,該文件內(nèi)部的widgets標(biāo)簽下需要添加一個(gè)新的widget入口。Sample Flex Viewer應(yīng)用程序支持widget在運(yùn)行時(shí)配置到相同的網(wǎng)絡(luò)服務(wù)器時(shí)的相對(duì)路徑。這個(gè)新添加的widget標(biāo)簽如下:
| <widget?label="A New Widget" icon="urlpath/myicon.png"menu="menuWidgets" config=”youconfig.xml”>relative/urlpath/MyNewWidget.swf</widget> |
如果你將widget配置到了另外一個(gè)網(wǎng)絡(luò)服務(wù)器,那么增加的widget表情里面的Url應(yīng)該是一個(gè)完整路徑。比如,應(yīng)用到Icon圖像如下:
| <widget?label="A New Widget"?icon="http://another-host/urlpath/myicon.png"menu="menuWidgets"config=”yourconfig.xml”>http://another- host/urlpath/MyNewWidget.swf</widget> |
你可以在widget中明確指定一個(gè)配置文件。在這個(gè)代碼中,定義于BaseWidget的的全局屬性configXML也能夠在widget中用到。目前,盒外開發(fā)的Sample Flex Viewer的應(yīng)用程序只支持XML格式的配置文件并且能夠自動(dòng)地構(gòu)建configXML屬性。如果你想在自己的widget代碼中分析配置數(shù)據(jù)的話該配置文件可以使用任意格式。
第三步:刷新Sample Flex Viewer應(yīng)用。當(dāng)下次Sample Flex Viewer應(yīng)用程序被刷新時(shí),新建的widget的配置將會(huì)被自動(dòng)識(shí)別并且這個(gè)widget能夠在用戶界面中通過tool菜單(或者在config.xml文件中自定義的菜單)調(diào)用。
4.3?安全性考慮
4.3.1?crossdomain.xml
一個(gè)雖法律上站不住但事實(shí)上卻普遍認(rèn)知的網(wǎng)絡(luò)瀏覽器標(biāo)準(zhǔn)就是把安全沙盒強(qiáng)加到瀏覽器的插件中。這就意味著當(dāng)前網(wǎng)頁(yè)運(yùn)行的插件只能夠訪問通過相同網(wǎng)絡(luò)服務(wù)器提供的遠(yuǎn)程資源。而Flash這個(gè)運(yùn)行基于Flash開發(fā)的軟件的瀏覽器插件也會(huì)受到同樣的基于Flash開發(fā)的應(yīng)用的沙盒限制。然而默認(rèn)情況下,一個(gè)Flash應(yīng)用只有在其他網(wǎng)絡(luò)服務(wù)器部署有一個(gè)crossdomain.xml文件的情況下才能從該服務(wù)器URL的根目錄下通過相關(guān)的Flash應(yīng)用訪問遠(yuǎn)程資源。
最簡(jiǎn)單形式的crossdomain.xml文件如下:
| <cross-domain-policy?xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd"> <allow-access-from domain="*"/> ? </cross-domain-policy> |
這個(gè)crossdomain.xml文件能夠訪問由任何網(wǎng)絡(luò)上的服務(wù)器提供服務(wù)的Flash應(yīng)用程序。可以參考Adobe Flex的文檔來了解設(shè)置這個(gè)文件的更多內(nèi)容。注意:不管任何時(shí)候,只要運(yùn)行Sample Flex viewer程序時(shí)發(fā)生了安全異常,就要及時(shí)檢查crossdomain.xml所部屬的資源服務(wù)器(比如ArcGIS的地圖服務(wù)),哪怕只是自己內(nèi)部組織的錯(cuò)誤。
4.3.2?網(wǎng)絡(luò)資源代理
在許多情況下,你需要訪問其他服務(wù)器所提供的資源,比如,各種GeoRSS在線反饋。如果這些反饋的服務(wù)器并沒有配置crossdomain.xml文件,那么唯一的選擇就是在自己由Flash部署的服務(wù)器上設(shè)置一個(gè)網(wǎng)絡(luò)資源代理,并且在代碼中指定相關(guān)代理。
這個(gè)鏈接提供了一些有關(guān)代理的更多資料
http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jshelp_start.htm#jshelp/ags_pro xy.htm
附錄: Configuration XML
關(guān)于config.xml配置文件的更多解釋請(qǐng)參閱源代碼中的readme.txt文件。
對(duì)于開發(fā)者,可以參考發(fā)布包里doc/ConfigXMLSchema目錄下的xml配置文件,這里定義了config.xml文件中具體的XML標(biāo)簽。
http://blog.csdn.net/zhangchuanguo99/article/details/6324998
轉(zhuǎn)載于:https://www.cnblogs.com/dview112/archive/2013/05/14/3077999.html
總結(jié)
以上是生活随笔為你收集整理的FlexViewer入门资料的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2013年1季度中国汽车品牌口碑研究报告
- 下一篇: BeyondCompare