[教學]Mate Framework Part2

part1介紹過Mate架構跟流程,這次寫一個簡單範例來說明Mate的寫法

範例為使用DataGrid操作來自DataManager的資料。按此觀看範例

原始檔下載

2009-06-04_131314.jpg

Main.mxml

同上次的架構,程式的進入點是Main.mxml,裡面只要宣告EventMap、ModelMap跟要使用的UI

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
xmlns:maps="idv.gd.hellomate.maps.*"
xmlns:view="idv.gd.hellomate.views.*"
width="600" height="350">        
<mx:Style source="assets/style.css"/>
        
        <maps:MainEventMap/>
<maps:ModelMap/>
<view:DataList/>
</mx:Application>

DataList.mxml

DataList.mxml 為列表的UI,負責顯示、新增及刪除,在Mate架構中,UI的Domain Logic直接寫在mxml,或許會有點亂,但這種寫法也方便Mate做Data Binding

<!-- 部分程式碼 -->    
<!-- mate特有的Dispatcher,即使元件不在顯示列表或不可見,仍可送訊息給Mate -->
<mate:Dispatcher id="deleteAllDispatcher" 
generator="{ListEvent}"
type="{ListEvent.REMOVE_ALL}">
<!-- 可直接接收來自EventMap的回應 -->
<mate:ResponseHandler type="deleteItemResponse" response="Alert.show('ok')"/>
</mate:Dispatcher>

<!-- 能監聽自己內部跟Mate事件 -->
<mate:Listener type="{NavigationEvent.ADD_STATE}" receive="stateChangeHandler(event)"/>
<mate:Listener type="{NavigationEvent.LIST_STATE}" receive="stateChangeHandler(event)"/>
 <mx:DataGrid id="myDG" 
x="10" y="10" 
width="560" height="215"
dataProvider="{currentListAC}">
<mx:columns>
<mx:DataGridColumn headerText="標題" dataField="title"/>
<mx:DataGridColumn headerText="訊息" dataField="message"/>
</mx:columns>
</mx:DataGrid>

事件可由Mate的Dispatcher送出,也可使用原本的EventDispatcher,但事件的bubbles一定要為true,而<listener>的標籤可以聽到來自Mate的事件,但自己Bubbles上來的事件也會聽到,在設計時要注意

三種在Mate中傳事件的寫法:

一、使用<Dispatcher>:<mate:Dispatcher id="deleteAllDispatcher" generator="{ListEvent}" type="{ListEvent.REMOVE_ALL}">,用調用時呼叫 deleteAllDispatcher.generateEvent();

二、使用原生的EventDispatcher:this.dispatchEvent(new NavigationEvent(NavigationEvent.ADD_STATE));,由於事件bubble為true,EventMap可聽到事件

三、使用程式碼的Mate Dispatcher: var mateDispatcher:Dispatcher = new Dispatcher(); mateDispatcher.dispatchEvent(listEvent);

ListEvent.as

自定事件,寫法同一般Flash事件寫法,但為避免混淆,Mate建議在事件的常數後加上Class名,好讓事件不會重覆

public class ListEvent extends Event
{
//常數後加上Class名,避免名稱重覆
public static const DELETE:String = "deleteListEvent";
public static const REMOVE_ALL:String = "removeAllListEvent";
public static const ADD:String = "addListEvent";

public var item:ItemInfo;

//bubbles要為true,給EventMap聽
public function ListEvent(type:String, bubbles:Boolean = true, cancelables:Boolean = false, item:ItemInfo = null)
{
super(type, bubbles, cancelables);
this.item = item;
}

override public function clone():Event
{
return new ListEvent(type, bubbles, cancelable, item);
}
}

DataManager.mxml

為管理列表資料的Manager

        public class DataManager
{
public var listArrayCollection:ArrayCollection;

public function DataManager()
{
listArrayCollection = new ArrayCollection();
listArrayCollection.addItem(new ItemInfo("first item", "hello mate"));
listArrayCollection.addItem(new ItemInfo("second item", "test"));
}

public function deleteItem(item:ItemInfo):void
{
if (listArrayCollection)
listArrayCollection.removeItemAt(listArrayCollection.getItemIndex(item));
}

public function deleteAllItem():void
{
if (listArrayCollection)
listArrayCollection.removeAll();
}

public function addItem(item:ItemInfo):void
{
if (listArrayCollection)
listArrayCollection.addItem(item);
}
}

DataManager封裝了資料操作,這裡只外露一個listArrayCollection給外部View使用,也可把ModelManager做為資料物件跟View挷定,但要記得要給class設[Bindable],或自定Binding事件

MainEventMap.mxml

為Mate事件的中心,用以管理事件及專案的Business Logic

<?xml version="1.0" encoding="utf-8"?>
<EventMap xmlns="http://mate.asfusion.com/" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import idv.gd.hellomate.events.*;
import idv.gd.hellomate.business.DataManager;
]]>
</mx:Script>

<!-- 監聽Mate事件,可呼叫Manager執行方法(Manager只會被生成一次)-->
<EventHandlers type="{ListEvent.DELETE}">
<MethodInvoker generator="{DataManager}" method="deleteItem" arguments="{event.item}"/>
</EventHandlers>

<EventHandlers type="{ListEvent.REMOVE_ALL}">
<MethodInvoker generator="{DataManager}" method="deleteAllItem"/>
<!-- 回應訊息給呼叫者 --> 
<ResponseAnnouncer type="deleteItemResponse"/>
</EventHandlers>

<EventHandlers type="{ListEvent.ADD}">
<MethodInvoker generator="{DataManager}" method="addItem" arguments="{event.item}"/>
<!-- 發送Navigation事件 -->
<EventAnnouncer generator="{NavigationEvent}" type="{NavigationEvent.LIST_STATE}" />
</EventHandlers>

其中<EventHandlers>的標籤為註冊Event要觸發的事件,這裡能調用ModelManager的方法,並可直接回傳內容(<ResponseAnnouncer>)或是呼叫事件(<EventAnnouncer>)

ModelMap.mxml

<?xml version="1.0" encoding="utf-8"?>
<EventMap xmlns="http://mate.asfusion.com/" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import idv.gd.hellomate.views.DataList;
import idv.gd.hellomate.business.DataManager;
]]>
</mx:Script>

<!-- 注入資料,DataList生成時自動注入 -->
<Injectors target="{DataList}" debug="true">
<PropertyInjector targetKey="currentListAC" source="{DataManager}" sourceKey="listArrayCollection"/>
</Injectors>
</EventMap>

ModelMap.mxml底層其實是EventMap,這裡分出來只是為了釐清架構。其中<Injectors>是很特殊的標籤,會在目標元件生成時自動把資料注入,且若是Bindable物件,之後就可靠物件自己更新,在寫法上很方便。

總結

這次只寫個簡單範例練習,由於Mate可用Data Binding,在寫法上會比PureMVC好寫很多,但實際上使用還是要看專案的複雜度,沒有人說那個MVC Framework是最好的,端看開發人員習慣那種架構。

這次的練習不夠完整,如果寫法或概念有錯還請指正,謝謝

0 意見 :: [教學]Mate Framework Part2