ButterKnife から Data Binding Library に載せ替える話


はじめに

Google IO 2015 で Data Binding ライブラリが発表されました。
当時は他のサポートライブラリと同様に dependencies に追加して使う感じだったのですが、Android Plugin for Gradle 1.5.0 から Build tools 内に取り込まれたようです。

面倒なfindViewById()を楽にする方法といえば ButterKnife が一般的でしたが、公式でサポートツールが提供されるのであれば乗り換えるのも検討する価値はあります。

このエントリを作成している Android Plugin for Gradle 1.5.0 時点ではまだ ベータ版とのことなので、仕様はまだ変わる可能性があります。

Data Binding Guide

Please note that the Data Binding library is a beta release.

準備

Android Plugin for Gradle を 1.5.0 以降に変更

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
    }
}

アプリプロジェクトでdataBinding を有効化

apply plugin: 'com.android.application'

android {
    // 省略
    dataBinding {
        enabled = true
    }
}

実装の置き換え

Fragment 内で ButterKnifeを使う場合、こんな感じの実装をしていたと思います。

my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

MyFragment.java
@Bind(R.id.textView)
TextView mText;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
    View v = inflater.inflate(R.layout.my_fragment, container, false);
    ButterKnife.bind(this, v);
    return v;
}

private void updateText(String text) {
    mText.setText(text);
}
これが Data Binding Library を使う場合はこうなります。

my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <RelativeLayout>
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </RelativeLayout>
</layout>

MyFragment.java
MyFragmentBinding mBinding;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
    View v = inflater.inflate(R.layout.my_fragment, container, false);
    mBinding = DataBindingUtil.bind(v);
    return v;
}

private void updateText(String text) {
    mBinding.textView.setText(text);
}

あまり変わっている感じがしませんが、my_fragment.xml には RelativeLayout を覆うように layout が追加されています。
MyFragment.java では、View 単体のインスタンスではなく、それらを抱える MyFragmentBinding のインスタンスを持っています。 MyFragmentBinding は、my_fragment.xml から自動的に生成されるクラスです。

何が変わったのか

上記の通り、findViewById をサボるためだけであれば大差ないです。

ですが、 Data Binding Library は名前の通り、オブジェクトのプロパティを View に自動的に反映するためのライブラリです。MVVM 的なことがしたければ使わない手はありません。(このエントリでは何も解説してないですが)

一方、ButterKnife の OnClick などのアノテーションに相当する機能も Data Binding Library は提供しています。

Binding Events

XML 側に Java のメソッド記述して、イベント発生時にそのメソッドが呼ばれます。Windows の XAML から C# のメソッドが呼ばれるのとほぼ同じです。
ただ、Android では(XML と Java のクラスが一意に結びついていないので?) IDE からのサポートが乏しく非常に使いにくいです。これだったら全て Java 側に setXxxListener を書いたほうが安全でわかりやすい気がします。

イベントアノテーションが気に入って ButterKnife を使っているのであれば、Data Binding Library には載せ替えないほうがよいかもしれません。あるいは、イベントアノテーションのために ButterKnife も残すというのも考えられます。

まとめ

そもそも Data Binding Library と ButterKnife では目指してることが違っていて、それを実現するための一部の機能が共通しているというだけでした。
公式の Data Binding Library が出たからさっさと置き換えという感じではなく、自分のアプリで重視する機能を持っている方を選べば良いのではないでしょうか(適当)。

個人的には、まだData Binding Library にはそこまで魅力を感じませんでした。
(というか、XAML+C# と比べると欠点ばかりが目立つ・・・)

コメント

このブログの人気の投稿

Lumia 920買った - LTE有効化と開発端末登録

Android で Unicode絵文字入力

Nexus 5 買った