余白

https://blog.lacolaco.net/ に移転しました

android-bindingでMVVMなAndroidアプリ開発 その3

前回から少し日があきましたが引き続きandroid-binding(AB)について書いていきます。今回は予告通りListViewのバインディングについて詳しく見ていきます。具体的には「ListViewに動的にクリック処理を持つ子を追加するボタン」を作ります。なんのこっちゃですね。実際に作りましょう。

まずはxmlの編集からです。前回から引き続きactivity_main.xmlを編集します。画面上にButtonとListViewを配置し、ButtonのtextonClickをまずバインディングしています。

次にListViewのバインディングですが、今回バインディングする属性はitemTemplateitemSourceclickedItem、そしてonItemClickedです。編集したxmlがこちら

itemTemplateは、ListViewに追加される子Viewのテンプレートになるxmlを指定します。今はまだ作っていないのでEclipseが赤線引いているはずです。itemSourceはそのとおりListViewのアイテムのソースオブジェクトです。clickedItemは読み取り専用の特殊な属性で、Object型を返す属性です。onItemClickedは言わずもがなですね。
それでは適当にitemTemplateに指定したlist_child.xmlをlayoutフォルダの中に作りましょう。

表示する文字列をバインディングできるようにしてあります。

xmlの編集が終わりましたが、ここで一つ疑問があると思います。ButtonとListView(activity_main.xml)を表示するActivityはMainActivityで、対応するViewModelは前回も使ったMainActivityModelです。しかしこのlist_child.xmlに対応するViewModelはどうするのでしょうか。
答えは簡単、ListChildViewModelを作るのです。というわけで早速ListChildViewModel.javaを作ります。前回までの解説を読んでいただけていればこのコードは解説不要のはずです。

次にMainActivityModelを編集します。Toast用にEventAggregatorの部分は残して他をまっさらにして、先程activity_main.xmlバインディングしたオブジェクトをもたせます。

新しく登場したのはArrayListObservableObjectObservableですね。ArrayListObservableは変更通知機能がついたArrayListで、主にListViewのバインディングに使われます。ジェネリクスコンストラクタに子ViewのViewModelを指定することで、任意のレイアウトの子Viewが生成できます。
ObjectObservableは変更通知機能がついたObjectで、主に読み取り専用のバインディングに用いられます。get()したあとキャストすることで任意のインスタンスを扱います。
addChildでは新しいListChildViewModelのインスタンスを生成し、リストに追加しています。追加していく様子がわかりやすいようにカウンタを回しています。onItemClickedではタッチした子ViewのViewModelをclickedItemから取得し、eventAggregatorを用いてToastを表示しています。
MainActivityはこうなっています。前回から第2引数の部分を直接Stringオブジェクトを送ることで簡単になっています。

これで完成です。いかがでしたでしょうか。
ABを使えばListViewにAdapterは必要ありません。子ViewのレイアウトにInflaterを使ってViewインスタンスを生成して追加する必要もありません。ViewModelを作ってListに追加するだけです。簡単でしょう?
レイアウトはxmlだけで作り、ロジックはViewModelだけで取り回す。これこそMVVMでは無いでしょうか

今回はこれで終わりです。前回から今回までの数日の間にさらにABのすごいところを発見してしまっていつになったら紹介が終わるのか定かではないですが、次回は「バインドできる属性と"Custom Bindable View"について」の解説をします。 それでは