Flex Framework Mate の基本的な使い方 その2


前回の続きです。
http://qiita.com/tajihiro/items/61a377c17b99fcff453c

サンプル

下記の図のようなサンプルです。
テキストフィールドに入力した言葉を、ラベルに返すサンプルです。


 ↓

ソースコード解説

アプリケーションエントリ

Index.mxmlは、アプリケーションのエントリとなるmxmlファイルです。
ここでは、Viewコンポーネントである MainView.mxml(View)を配置し、MainView上で発生するイベントをマッピングする MainViewEventMap.mxml (EventMap)を定義します。

Index.mxml
<?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が使用するモデルの変数名となります。

MainViewEventMap.mxml
<?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に入力した文字列を引数にして呼び出しています。

Main.mxml
<?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でのイベントハンドラ処理等のロジックを記述します。
または、イベントディスパッチされたイベントの後処理を記述します。

MainViewModel.as
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クラスを継承しており、イベントの定義を行います。
イベントクラス内では、発生したイベントにパラメータを含めたい場合には、インスタンス変数を定義します。

MainViewEvent.as
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の基本的な解説でした。
最初は複雑なので戸惑います。
ソースコードや、イベントディスパッチを追うのがとても面倒なのですが、大規模開発の見通しは良いと思います。