Data BindingがButterKnifeの代わりになるのか試してみる

こんにちは、Androidエンジニアの梅津です。

Google I/O 2015で発表になったData Binding。
データ元となるクラスとViewを結び付けるもので、データの変更に合わせてViewの状態も変更してくれます。
すごい便利そうじゃん!と思って気にはなっていたんですが、なんだかんだで触っていませんでした。

そんな中、使い方によってはData BindingがButter Knifeの代わりになるという話を聞いたので今回試してみることにしました。

※Data Bindingは現在ベータリリースの状態です。
正式版が出た時にはここで書いた内容から変わる可能性がありますのでご注意ください。
導入方法
さっそく触っていきましょう。
まずはData Bindingをプロジェクトで使えるように設定していきます。
build.gradleを下記のように編集します。
 

次にapp/build.gradleに下記を付け加えます。


これで準備は完了です。

Hello Data Binding!
ButterKnifeとの使い方を比較する前に、Data Bindingの基本的な使い方を見てみることにします。

まずはデータとなるクラスを作ります。
今回はUserクラスというのを作りました。


次にレイアウトxmlにData Binding用の記述を追加していきます。


Data Bindingで処理をさせるには、layoutタグで全体を囲む必要が有ります。
dataタグは変数の宣言などを行うための親要素です。
variableタグで実際の変数を宣言します。
xml内で変数を使用する時は android:text="@{user.name}" のように @{} で囲んであげます。

続いてUserクラスとレイアウトをBindしましょう。

ActivityHelloDataBindingBindingというクラスが自動的に作られています。
このインスタンスをDataBindingUtilクラスを使って生成しましょう。
作ったActivityHelloDataBindingBindingのインスタンスに対して setUser してあげれば完了です。
自分でTextView#setTextなどを呼ぶ必要はありません。
実行してみると、Userのnameに設定した値が表示されています。
中々便利そうですね。

device-2015-11-12-154331

 
Fragment内でBindingクラスを使う場合
先ほどのサンプルではDataBindingUtil#setContentViewメソッドを使ってBindingクラスを生成しました。
しかし、これはActivity内でのみ使えるもので、Fragmentの中などでは使えません。
それではどうするかというと、Bindingクラス自身が持っているbindメソッドを使うことで解決できます。


ButterKnifeの代わりになるか試す
ここまででData Bindingの基本的な使い方がわかりました。
それでは本題であるButterKnifeの代わりになるのかを見ていきましょう。

ViewのBindをしてみる
ButterKnifeの主な機能といえば、やはりViewのBindです。
これによっていちいちfindViewByIdでViewを取り出してフィールドにセットするという処理から解放されました。

Data BindingはViewのBindにも使えるのでしょうか。
 
実はBindingクラスは、レイアウトのViewをフィールドとして保持しています。
Bindingクラスのフィールドは普段privateになっているため、外部からアクセスすることはできません。
しかし、xmlでidを振ったViewに関してはpublicになりアクセスすることが可能になります。


Bindingクラスのインスタンス越しにtextやbuttonにアクセスできています。

このようにBindingクラスを通してViewにアクセスするようにすれば、ButterKnifeの代わりになりそうですね。  

ViewHolderパターンを置き換える
ちなみにこの機能を使ってViewHolderパターンを置き換えることが可能です。
その際にはBindingクラスのinflateメソッドを利用します。 


ListenerのBindをしてみる
ButterKnifeのもう一つの機能にListenerのBindがあります。
Data Bindingでも同じようなことが出来るのか試してみましょう。

ListenerのBindは、Hello Data Binding!のところで紹介したサンプルと似たような感じになります。
まずはレイアウトのxmlから。
app:onClickListener="@{activity}" の部分がButtonに対してListenerをセットする記述になります。
TextViewに対して android:text="@{user.name}" とした時と少し似ていますよね。 

Activity側はこうなります。

ActivityにView.OnClickListenerを実装するのが嫌な場合、
View.OnClickListenerをフィールドとして持つこともできます。
その場合は以下のようになります。


本当にButterKnifeから乗り換えるか
今回Data Bindingを触ってみて以下のような感想を持ちました。
 
【良いところ】 
* ViewのBindはすごく使いやすい!
* 特にViewを直接フィールドとして持つわけではないのでレイアウトの変更に強いのが良い。
* ButterKnifeを使っている時、xml側で型の変更をしたりViewの削除をしたのにActivity/Fragment側の更新を忘れて実行時エラーになることがあった。
* Data Bindingの場合はActivity/Fragment側でコンパイルエラーになってくれたり、そもそも変更が必要なかったりするので嬉しい。

【気になったところ】
* レビューしづらそう
* ListenerのBindのあたりは、Activity/Fragmentを見ただけではどこで何をされているのかわかりづらい。
* とくにListenerをフィールドで持つような場合はListenerのゲッターを作るけど、そのゲッターがどこで呼ばれているのかわからない。Android StudioのFind Usageでも使用箇所が引っかからなかったのでパッと見困惑しそう。
* チーム内で書き方のルールを決めていけば問題なさそう?

機能面だけで見ればButterKnifeの代わりには十分なりそうですが、
すぐにData Bindingに移行するかと言われるとすこし迷ってしまいます。

たしかに色々と出来て便利なんですが、ListenerのBindのところなんかは他の人が読みづらそうだなーと感じました。
しっかりと運用ルールを作って利用していく必要がありそうですね。

もうしばらくはButterKnifeを使って、正式版がでた頃にまた検討してみようかなと思います。

以上、お疲れさまでした。