ホーム >> 左脳Script >> Adobe AIR >> Flex >> Bindable の仕組み

Bindable の仕組み


Flex において大変便利な Bindable 機能について、実は良くわかっていなかったので(主に仕組みが)調べてみました。

Bindable 基礎

とにかく判りやすい機能のサンプルコード。
custom.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml" change="onChange()">
    <mx:Script>
        <![CDATA[
            [Bindable] public var itemString:String;
            private function onChange():void
            {
                itemString = selectedItem as String;
            }
        ]]>
    </mx:Script>
    <mx:dataProvider>
        <mx:ArrayCollection>
            <mx:Array>
                <mx:String>A:アセンブラ</mx:String>
                <mx:String>B:ベーシック</mx:String>
                <mx:String>C:C言語</mx:String>
                <mx:String>D:D言語</mx:String>
                <mx:String>E:えっ?</mx:String>
            </mx:Array>
        </mx:ArrayCollection>
    </mx:dataProvider>
</mx:ComboBox>
Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*">
    <mx:Label text="{id1.itemString}"></mx:Label>
    <my:custom id="id1" width="100" height="30"/>
</mx:Application>

この例では、コンボボックスの内容が変化すると、上部のラベルにその変化が反映されます。
custom コントロールの、itemString が [Bindable] です。


子コンポーネントから子コンポーネントへの情報伝達は、Bindable を使えば容易に実現できることが判ります。


親が変化を検出するには

では、親コンポーネントが直接子コンポーネントの変数の変化を知るにはどうしたらよいかと言うと・・・

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*" applicationComplete="init()">
    <mx:Script>
        <![CDATA[
        import mx.events.PropertyChangeEvent;
        private function init():void 
        {
            id1.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChange);
        }
        private function onChange(e:PropertyChangeEvent):void 
        {
            lb.text = e.newValue as String;
        }
        ]]>
    </mx:Script>
    <mx:Label id="lb"/>
    <my:custom1 id="id1" width="100" height="30"/>
</mx:Application>
Bindable 変数を持っているコンポーネントに対して、PropertyChangeEvent.PROPERTY_CHANGE を監視するイベントリスナーを指定します。上記のコードは冒頭のサンプルと同じ動作をします。

これで、子コンポーネントの Bindable 変数の変化を親コンポーネントで感知する事が出来るようになりました。

Bindable の更新通知の仕組みはイベントで有る事がわかります。


変数が複数あったら・・・

子コンポーネントから子コンポーネントへの情報伝達は、素直に記述できます。

custom2.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:HSlider id="xBar" width="100" change="onChangeX()"></mx:HSlider>
    <mx:VSlider id="yBar" height="100" change="onChangeY()"></mx:VSlider>
    <mx:Script>
        <![CDATA[
            private function onChangeX():void
            {
                xSize = xBar.value;
            }
            [Bindable] public var xSize:Number;
            private function onChangeY():void
            {
                ySize = yBar.value;
            }
            [Bindable] public var ySize:Number;
        ]]>
    </mx:Script>
</mx:HBox>
Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*">
    <mx:Label id="lbX" text="{id1.xSize}" />
    <mx:Label id="lbY" text="{id1.ySize}" />
    <my:custom2 id="id1"/>
</mx:Application>


Flexは、どうやって各プロパティを区別しているのか?

Bindable 変数を持ったコンポーネントの PropertyChangeEvent.PROPERTY_CHANGE を監視すればよいのは判りましたが、変数が複数あった場合、どの変数が変化しても PropertyChangeEvent.PROPERTY_CHANGE が発生します。

そこで、PropertyChangeEvent を調べてみると、property という物があるようです。これは、変化&更新のあった変数名を格納しているプロパティです。
→参照:http://www.adobe.com/livedocs/flex/3_jp/langref/mx/events/PropertyChangeEvent.html

前述のコードを以下のように修正し、トレースを観察してみます。

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*">
    <mx:Script>
        <![CDATA[
        import flash.events.Event;
        import mx.events.PropertyChangeEvent;
        private function init():void 
        {
            id1.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChange);
        }
        private function onChange(e:PropertyChangeEvent):void 
        {
            trace("property=" + e.property.toString());
        }
        ]]>
    </mx:Script>
    <my:custom2 id="id1"/>
</mx:Application>

プロパティ名の「xSize」「ySize」が動作に応じてトレースされるのがわかると思います。

  • PropertyChangeEvent.PROPERTY_CHANGE を監視し、PropertyChangeEvent.property で示されるプロパティ名に応じて処理を振り分ける。
が、王道なのでしょう。

Flex がこのように作られている事から、

→コンポーネントに含まれるBindable変数は少ない方が良い。
→コンポーネントの粒度はより細かい方がよい?(プロパティの数に準ずる

と考える事も出来ますね。


Bindable イベント指定

Bindableは、任意の発行 event を指定が出来るような記述がありますが、 結局自前のコードでイベントを発行しなければなりません。
→参照:http://www.adobe.com/livedocs/flex/3_jp/html/help.html?content=databinding_8.html

場合にもよりますが、極論、Bindableを指定する意味が損なわれてしまいます。特にこのサンプルのような場合は、Bindable 指定する意味すらなく、只の public変数で十分です。

custom3.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:HSlider id="xBar" width="100" change="onChangeX()"></mx:HSlider>
    <mx:VSlider id="yBar" height="100" change="onChangeY()"></mx:VSlider>
    <mx:Script>
        <![CDATA[
            import flash.events.Event;
            private function onChangeX():void
            {
                xSize = xBar.value;
                dispatchEvent(new Event("XEVENT"));
            }
            [Bindable(event="XEVENT")] public var xSize:Number;
            private function onChangeY():void
            {
                ySize = yBar.value;
            }
            [Bindable] public var ySize:Number;
        ]]>
    </mx:Script>
</mx:HBox>
Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*">
    <mx:Script>
        <![CDATA[
        import flash.events.Event;
        import mx.events.PropertyChangeEvent;
        private function init():void 
        {
            id1.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChange);
            id1.addEventListener("XEVENT", onChangeX);
        }
        private function onChange(e:PropertyChangeEvent):void 
        {
            lbY.text = e.newValue.toString();
        }
        private function onChangeX(e:Event):void 
        {
            lbX.text = id1.xSize.toString();
        }
        ]]>
    </mx:Script>
    <mx:Label id="lbX"/>
    <mx:Label id="lbY"/>
    <my:custom3 id="id1"/>
</mx:Application>
X軸の変化は、自力実装イベントで、Y軸は Bindable で処理しています。
この例では、Bindable の event記述をしていますが [Bindable(event="XEVENT")] は無くても動作に変化はありません。


まとめ

Bindable は、「手放しで便利だから使うべき。」「とりあえず使っとけ。」という程の物でもないようです。そこは適材適所、使いよう。

例えば「複数のプロパティが更新された際、コンポーネントの内容を描画し直したい」と言う場合、 該当の変数が Bindable 指定されていれば、PropertyChangeEvent.PROPERTY_CHANGE の監視だけで、更新作業を行う事が出来ます。
→参照:http://d.hatena.ne.jp/secondlife/20070326/1174904664

逆に、ガッチリ各プロパティの更新を区別をしたい場合、つまるところ自力での更新イベント実装にした方が良い場合もあります。

Flex コンポーネント作成の際は、本当に Bindable で実装するべきなのかを良く考える必要が有ると言えるでしょう。


雑感

検索でヒットする、Flex の Bindable に関する記事の殆どが「このように記述すれば使える」という使用法に関する物ばかりでした。その動作や仕組みについて突っ込んだ記事が"殆ど"なかったので、纏めて見たのですがイカがでしょうか?




トラックバック(0)

トラックバックURL: http://n-yagi.0r2.net/sanoupulurun/mt-tb.cgi/255

コメントする

ホーム >> 左脳Script >> Adobe AIR >> Flex >> Bindable の仕組み

アーカイブ

このブログ記事について

このページは、n-yagiが2010年2月10日 20:56に書いたブログ記事です。

ひとつ前のブログ記事は「HTMLコントロールのリンクイベント」です。

次のブログ記事は「軽量Webサーバーmattows」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Creative Commons License
このブログはクリエイティブ・コモンズでライセンスされています。