前回の続きです。
http://qiita.com/tajihiro/items/61a377c17b99fcff453c
サンプル
下記の図のようなサンプルです。
テキストフィールドに入力した言葉を、ラベルに返すサンプルです。
ソースコード解説
アプリケーションエントリ
Index.mxmlは、アプリケーションのエントリとなるmxmlファイルです。
ここでは、Viewコンポーネントである MainView.mxml(View)を配置し、MainView上で発生するイベントをマッピングする MainViewEventMap.mxml (EventMap)を定義します。
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955"
minHeight="600"
xmlns:view="main.view.*"
xmlns:map="main.map.*">
<fx:Declarations>
<!-- 使用するEventMapを 以下に追記する -->
<map:MainViewEventMap/>
</fx:Declarations>
<s:Group top="20"
left="20">
<!--MainViewを配置する-->
<view:MainView/>
</s:Group>
</s:Application>
イベントマップ
このファイルは、Index.mxmlファイル内で呼び出されます。
イベントマップファイルの中では、Flexの初期イベントであるPREINITIALIZEイベントを受けて、MainViewModelクラスをインスタンス化します。
その際、モデルのコンストラクタにて scope.dispathcer を注入(DI)してあげます。
イベントハンドラのマッピング定義ですが、EventHandlersタグの、typeで指定したイベントを受け取ると、MethodInvokerのgeneratorで指定したモデルクラスのメソッドを呼び出します。
Injectorsにてターゲットに Viewコンポーネントを指定し、使用するモデルを定義します。ここで指定する targetKeyで指定した識別子が、Viewが使用するモデルの変数名となります。
<?xml version="1.0" encoding="utf-8"?>
<mt:EventMap 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:mt="http://mate.asfusion.com/">
<fx:Script>
<![CDATA[
import main.event.MainViewEvent;
import main.model.MainViewModel;
import main.view.MainView;
import mx.events.FlexEvent;
]]>
</fx:Script>
<fx:Declarations>
<!-- Modelのインスタンス化 dispatcherを引数とする -->
<mt:EventHandlers type="{FlexEvent.PREINITIALIZE}">
<mt:ObjectBuilder generator="{MainViewModel}"
constructorArguments="{scope.dispatcher}"/>
</mt:EventHandlers>
<!-- Eventに対応するModel内のメソッドを定義する パラメータは event より取得-->
<mt:EventHandlers type="{MainViewEvent.EXEC_FUNC_1}">
<mt:MethodInvoker generator="{MainViewModel}"
method="func1"
arguments="{event.inputData}"/>
</mt:EventHandlers>
<!-- ViewにModelをインジェクトする -->
<mt:Injectors target="{MainView}">
<mt:PropertyInjector source="{MainViewModel}"
targetKey="model"/>
</mt:Injectors>
</fx:Declarations>
</mt:EventMap>
Viewコンポーネント
Viewコンポーネントファイルでは、ボタン等のコンポーネントを配置します。
また、[Bindable]なモデルクラスを定義します。
Viewで発生したイベントは、そのイベントハンドラの中で、そのModelファイルへ処理を受け渡します。
この例では、ボタンのクリックイベントに対応した myButton_clickHandler(event)の中で、そのModelクラスのclickHandlerメソッドを、TextInputに入力した文字列を引数にして呼び出しています。
<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400"
height="300">
<fx:Script>
<![CDATA[
import main.model.MainViewModel;
[Bindable]
public var model:MainViewModel;
//クリックハンドラ
protected function myButton_clickHandler(event:MouseEvent):void
{
//モデルのクリックハンドラメソッドを呼ぶ
this.model.clickHandler(this.myText.text);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 -->
</fx:Declarations>
<s:HGroup>
<s:TextInput id="myText"
text="こんにちは。"/>
<s:Button id="myButton"
label="OK"
click="myButton_clickHandler(event)"/>
</s:HGroup>
<s:Spacer height="30"/>
<s:HGroup>
<s:Label text="戻り値:"/>
<s:Label id="result"
text="{this.model.result}"/>
</s:HGroup>
</s:VGroup>
モデルクラス
モデルクラスは、Viewでのイベントハンドラ処理等のロジックを記述します。
または、イベントディスパッチされたイベントの後処理を記述します。
package main.model
{
import com.asfusion.mate.events.Dispatcher;
import flash.events.IEventDispatcher;
import flash.events.MouseEvent;
import main.event.MainViewEvent;
import main.view.MainView;
import mx.controls.Alert;
public class MainViewModel
{
/**
* コンストラクタ
*/
public function MainViewModel(dispatcher:IEventDispatcher)
{
this.dispatcher=dispatcher;
}
//親クラスで定義した方が便利
protected var dispatcher:IEventDispatcher;
/**
* プロパティ
*/
private var _result:String;
/**
* プロパティ Getter/Setter
*/
[Bindable]
public function get result():String
{
return _result;
}
/**
* @private
*/
public function set result(value:String):void
{
_result=value;
}
/**
* クリックハンドラ(Viewから呼ばれる)
*/
public function clickHandler(value:String):void
{
var event:MainViewEvent=new MainViewEvent(MainViewEvent.EXEC_FUNC_1);
//Eventにパラメータを設定
event.inputData=value;
this.dispatcher.dispatchEvent(event)
}
/**
* イベントディスパッチされたハンドラ(EventMapから呼ばれる)
*/
public function func1(param:Object):void
{
var str:String=param as String;
result=str;
// Alert.show("func1:" + str);
}
}
}
Eventクラス
Eventクラスは、 flash.events.Eventクラスを継承しており、イベントの定義を行います。
イベントクラス内では、発生したイベントにパラメータを含めたい場合には、インスタンス変数を定義します。
package main.event
{
import flash.events.Event;
public class MainViewEvent extends Event
{
public static const NAME:String="MainViewEvent";
//イベント名
public static const EXEC_FUNC_1:String="execFunc1" + NAME;
//パラメータデータ
public var inputData:String;
public function MainViewEvent(type:String,
bubbles:Boolean=false,
cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
以上、FlexのフレームワークであるMateの基本的な解説でした。
最初は複雑なので戸惑います。
ソースコードや、イベントディスパッチを追うのがとても面倒なのですが、大規模開発の見通しは良いと思います。