Android Binding
以前、日本Androidの会のMLで話題に上がったAndroid BindingというAndroid用のフレームワーク。かなり気になっていたんですが、ホッタラカシになっていました。
なぜ気になっていたかというと、以前からAndroidアプリのプログラミングをしていて、Activityの規模がいつも大きくなってしまい、一枚岩のようになってしまうことが多かったからです。つまりAndroidアプリ=Activity (=画面) みたいになっていたのです。もっとActivityの規模を小さくして、よく言われるMVCモデルのように役割分担出来ないものかと考えていたんです。一枚岩の設計モデルってかっこ悪いですよね。複数人数で開発するときも障害になりそうだし。
ということでHello worldレベルから試してみることにしました。参考にしたサイトはこちら。
MVVMって何?
Android Bindingを使う前に、MVVM (Model-View-View Model) パターンについてですが、これが結構難しい。私が参考にしたサイトはこちら。
MVVMパターンとイベント駆動開発、そしてMVC/MVP/PMパターンとの関係 – 何故MVVMなのか
MVC (Model-View-Controller) を現代のUIコンポーネントに合わせて、ControllerとViewをくっつけて、ModelをUIに関わらないもの (Model) とUIに関係するもの (View Model) に分けた、というのが私の勝手な理解です。Viewが直接Modelを参照すると見た目を合わせるために結構なロジックが必要になります。このロジック部分がView Modelというわけです。
全て私の勝手な見解なのであしからず。
Tutorial: Hello Android (MVVM)
早速試してみます。まず必要なのはAndroid Bindingライブラリ。こちらからjarファイルをダウンロードして、プロジェクトに取り込みます。
現在最新はVersion 0.4 Preview 2というバージョンです。まだ正式バージョンではないんですね。今後が楽しみです。
Android BindingはApplicationクラスで初期化します。・・・恥ずかしながら初めてApplicationクラスを作成しました。
public class HelloApplication extends Application { @Override public void onCreate() { super.onCreate(); // Load Android Binding in the system. Binder.init(this); } }
そのままですね。Binder.initメソッドを使ってAndroid Bindingフレームワークを初期化しています。ここから始まるわけです。
次にViewを作成しましょう。ここでいうViewとはレイアウトファイルのことです。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:binding="http://www.gueei.com/android-binding/" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" binding:text="Greeting" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Change" binding:onClick="ChangeGreeting" /> </LinearLayout>
まずここで面白いのが、いつも辟易するandroid:id="@+id/...という記述がないことです。そもそもidはActivity内でViewを特定するために必要なものです。Android Bindingではレイアウトファイル内でViewとView Modelとをバインドするのでidが不要なのです。これだけでも私にとっては好感度超アップです。
話を戻します。レイアウトファイル内でViewとView Modelとをバインドしているのが、以下の記述です。
<TextView ... binding:text="Greeting" /> <Button ... binding:onClick="ChangeGreeting" />
TextViewとある文字列データをバインドするキーワードが
binding:text="Greeting"
です・・・って何コレ?ということでGreetingというキーワードでバインドされるView Model側を見てみます。
public StringObservable Greeting = new StringObservable("Hello from Android Binding");
もちろん単なるString型オブジェクトではありません。更新が発生したら自動的にViewに反映する必要があるので、StringObservableというAndroid Bindingフレームワーク固有のクラスを使います。こうすると、以下のようにGreetingインスタンスに変更を加えるとViewに自動的に反映されます。
Greeting.set("Greeting changed by command");
Android BindingフレームワークではこのようなデータのことをPropertyと言います。
もう一つのバインドは以下です。
binding:onClick="ChangeGreeting"
属性の名前から何となく想像が付きますが、これは先ほどのデータではなく、アクション (動作) をバインドします。ChangeGreetingというキーワードでバインドされるView Model側はこんな感じです。
public Command ChangeGreeting = new Command() { @Override public void Invoke(View arg0, Object... arg1) { Greeting.set("Greeting changed by command"); } };
Runnableインターフェイスに似ていますね。CommandインターフェイスはAndroid Bindingで定義されているインターフェイスです。先ほどのバインドはこのCommandインターフェイスとバインドしているんです。このアクションのことをCommandと言います。
実行するとこんな感じになります。
ボタンを押すと文字が変わるだけの簡単なプログラムですが、いつも書くようなこんなコードはどこにもありません。
Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { TextView text = (TextView)findViewById(R.id.text); text.setText("Greeting changed by command"); } });
こちらはいかにも更新するぜ!という分かりやすい感じもしますが、更新するViewが多くなればなるほど、抜けが発生したり、間違ったデータを設定してしまったりします。このような機械的な操作は自動化すべきです。そんな時にこのAndroid Bindingはとてもよいと思います。
もうちょっと掘り下げてみようかな。
なお、大した内容ではありませんが、上のサンプルプログラムをさらしておきます。