Flex模塊化開發優勢及技巧解析
本文和大家重點討論一下Flex模塊化開發的概念,模塊可以讓你將程序分割成幾個片段或單元。主程序或“殼”,可以動態的加載其它需要的模塊,不會在啟動時加載所有的模塊,也不會加載任何用戶尚未進行交互的模塊。
Flex模塊化開發
模塊是可以被一個程序加載和卸載的SWF文件。模塊不能獨立于程序運行,但是可以在任意數量的程序間共享。
模塊可以讓你將程序分割成幾個片段或單元。主程序或“殼”,可以動態的加載其它需要的模塊,不會在啟動時加載所有的模塊,也不會加載任何用戶尚未進行交互的模塊。當程序不再需要一個模塊時,可以卸載模塊來釋放內存和資源。
Flex模塊化程序有如下優點:
1.更小的初始階段SWF文件下載量;
2.更短的加載時間
3.更好的封裝程序的相關方面
模塊的好處
模塊是包含了一個IFlexModuleFactory類工廠的可動態加載的特殊類型的SWF。它允許一個程序在運行時加載代碼并創建類實例,而不需要類實現被鏈接到主程序。
模塊與運行時共享庫(RSLs)的共同點在于都從程序中將代碼分割到獨立加載的SWF文件中。但模塊比RLS更加靈活,因為模塊可以在運行時動態的加載、卸載,且在程序外被編譯。
兩個常見的使用模塊的場景是有著不同的用戶路徑的程序和一個門戶(portal)程序。
模塊API細節
模塊通過一個標準接口實現了一個類工廠。類工廠的產品實現了一個被“殼”所感知的接口,或“殼”實現一個可以感知模塊的接口。
通過使用公共接口定義,這些共享的接口可以減少“殼”與模塊之間的硬依賴。這提供了類型安全的通訊,以及不會增加SWF文件長度的強制的抽象層。
下圖展示了“殼”和模塊的接口之間的關系:
ModuleManager管理被夾在的模塊的集合,這些模塊被加工為以模塊URI為索引的單例的Map。加載一個模塊將觸發一系列事件使客戶端可以監視模塊的狀態。模塊總是只加載一次,但是之后的重加載還是會導讀事件,所以客戶端代碼可以被簡化,并且可放心的通過READY時間來感知模塊的類工廠是否對用戶可用。
ModuleLoader類是位于ModuleManagerAPI頂部的“薄層”(thinlayer)。ModuleLoader類是用于實現基于模塊架構的最簡單的類,而ModuleManager則提供了對模塊更全面的控制。
模塊的域
默認的,一個模塊被加載進當前程序域的一個子域。你可以通過ModuleLoader類的applicationDomain定義一個不同的程序域。
因為一個模塊被夾在到一個子域,它自己的淚定義不會在主程序的域中。例如,第一個模塊通過加載PopUpManager類而成為在整個程序中PopUpManager類的擁有者,因為該模塊使用SingletonManager注冊了管理器。如果其他模塊在之后嘗試使用PopUpManager,AdobePlayer將拋出一個異常。
解決方案是確保例如PopUpManager和DragManager之類的管理器一級其他被共享的服務都被主程序定義(或者之后被記載到“殼”程序的域中)。當你將這些類中的而一個提升到“殼”中,這個類就可以被所有的模塊使用。典型的,通過添加下面的腳本塊來實現:
- importmx.managers.PopUpManager;
- importmx.managers.DragManager;
- privatevarpopUpManager:PopUpManager;
- privatevardragManager:DragManager;
這個技巧同樣殼被應用于組件。模塊首先使用屬于其自身的且定義于其自身域中的組件。結果是,如果其他模塊嘗試使用一個已經被另一的模塊所以用的組件,那么它的定義不會匹配已經存在的定義。要避免組件定義被錯誤的匹配,就要在主程序中創建一個組件的實力。這樣,那個組件的定義將被主程序應用,并且可以被其他任何字域中的組件使用。
因為一個Flex模塊在于加載它的程序相同的安全域中,當你在一個AIR程序中使用模塊時,任何的模塊SWF文件必須位于與主程序SWF文件相同的目錄或位于主程序SWF文件所在目錄的子目錄中,以確保主程序SWF和模塊SWF位于AIR程序的安全沙箱中。這一點可通過模塊的路徑不需要"../"記號來從程序目錄或程序的某個子目錄向外導航加以印證。
Flex模塊化程序
要創建一個Flex模塊化的程序,你要為每個模塊創建獨立的類,以及加載這些模塊的程序。
創建一個Flex模塊化程序
1.創建任意數量的模塊。一個基于MXML的模塊文件的根標記是<mx:Module>。基于ActionScript的模塊繼承自Module或ModuleBase類。
2.編譯每個模塊。你可以使用mxmlc命令行編譯器或AdobeFlexBuilder內建的編譯器進行編譯。
3.創建一個Aplication類,可以是一個典型的根元素為<mx:Applicaton>的MXML文件,也可以是一個只有ActionScript的程序。
4.在Application文件中,使用<mx:ModuleLoader>標簽來加載每個模塊。你也可以使用mx.modules.ModuleLoader和mx.modules.ModuleManager類的方法來加載模塊。
編寫模塊
模塊是就像程序文件一樣的淚。你可以在ActionScript中創建它們,也可以通過使用MXML標簽擴展Flex類的方法創建它們,即:你可以在MXML或ActionScript中創建模塊。
創建基于MXML的模塊
要在一個MXML種創建模塊,你需要通過創建一個根元素為<mx:Module>的MXML文件來mx.modules.Module類。在那個標簽中,可以添加任意的命名空間。你必須在文件頭包含XML類型生命標簽,如下所示:
- <?xmlversionxmlversion="1.0">
- <mx:Modulexmlns:mxmx:Modulexmlns:mx="http://www.adobe.com/2006/mxml"width="100%"height="100%">
- <mx:Script>
- <![CDATA[
- importmx.collections.ArrayCollection;
- [Bindable]
- publicvarexpenses:ArrayCollection=newArrayCollection([
- {Month:"Jan",Profit:2000,Expenses:1500},
- {Month:"Feb",Profit:1000,Expenses:200},
- {Month:"Mar",Profit:1500,Expenses:500}
- ]);
- ]]>
- </mx:Script>
- <mx:ColumnChartidmx:ColumnChartid="myChart"dataProvider="{expenses}">
- <mx:horizontalAxis>
- <mx:CategoryAxis
- dataProvider="{expenses}"
- categoryField="Month"
- />
- </mx:horizontalAxis>
- <mx:series>
- <mx:ColumnSeries
- xField="Month"
- yField="Profit"
- displayName="Profit"
- />
- <mx:ColumnSeries
- xField="Month"
- yField="Expenses"
- displayName="Expenses"
- />
- </mx:series>
- </mx:ColumnChart>
- <mx:LegenddataProvidermx:LegenddataProvider="{myChart}"/>
- </mx:Module>
在你編譯一個模塊后,你可以在一個程序或另一個模塊中加載它。你可以用下面介紹的技巧來加載基于MXML的模塊:
ModuleLoaderModuleLoader類提供了高層的處理模塊的API。
ModuleManagerModuleManager類提供了較ModuleLoader更底層的處理模塊的API。
創建基于ActionScript的模塊
要在ActionScript中創建一個模塊,你可以創建一個繼承自mx.modules.Moddule類或mx.moduls.ModuleBase類的文件。
擴展Module類與在MXML文件中使用<mx:Module>標記的效果相同。如果你的模塊與框架交互,就應該擴展這個類。這意味著將向顯示列表添加對象,或與顯示對象發生交互。
要查看一個擴展Module類的ActionScript類的例子,可以先創建一個根元素為<mx:Module>的MXML文件。當你編譯這個文件的時候,將keep-generated-actionscript編譯選項設定為true。Flex的編譯器將在一個叫做generated的目錄中保存生成的類。你將注意到生成的類中包含著一些你可能尚不了解的代碼,其結果是你可能無法編寫擴展Module類的基于ActionScript的模塊,而是使用MXML文件的方式來代替。
如果你的模塊不包含任何框架代碼,你可以創建一個繼承自ModuleBase的淚。如果你使用ModuleBse類,你的模塊將比使用基于Module類的時候更小,因為它不包含任何依賴的框架代碼。
下面的例子創建了一個簡單的、不包含任何框架代碼的,且繼承自ModuleBase類的模塊:
- package{
- importmx.modules.ModuleBase;
- publicclassSimpleModuleextendsModuleBase{
- publicfunctionSimpleModule(){
- trace("SimpleModulecreated");
- }
- publicfunctioncomputeAnswer(a:Number,b:Number):Number{
- returna+b;
- }
- }
- }
【編輯推薦】