Enter

日々感じたことを記録するブログ

Android DataBinding 入門 ① ~オブジェクト変化を監視するぞ~

はじめに

最近Androidで,Viewを取ってくるときによく使うfindViewByIdをぶっとばすために ButterKnifeを使うことを検討していた.
しかしButter Knife、今までありがとう。 Data Binding、これからよろしく。の記事を見たり,「DataBindingいいよ」という話を聞き,
標準で使えるDataBindingを使ってみようと思ったので,
連載形式で勉強していきたいと思う.
(RxAndroidもやっていく予定...宣言しておく!)

DataBindingとは?

まず,DataBindingについて整理していこう. 公式ドキュメントはここ. developer.android.com

DataBindingの言葉の意味はwikipediaによると,

XMLなどのデータソースとアプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術である。

分離されたデータソースとユーザインタフェースの間を橋渡しする役割を果たし、データが変更されるとそれに応じてユーザインタフェースが変更される一方向なデータバインディングと、 併せてユーザインタフェースの変更または操作に応じてデータが変更される双方向のデータバインディングがある。

重要な点としては,分離されたデータソースとUIの間の橋渡しをする役割であること.
これを最小限のコード量で実現できるのがDataBinding Libraryだと締めておく.

DataBindingを導入

Android StudioのプロジェクトでDataBindingを使えるようにするには, appディレクトリ以下のbuild.gradleにこれを追加するだけ!

android {
       ......
       dataBinding{
        enabled = true
    }
}

Android Studio 1.3以降がサポートしています. https://developer.android.com/topic/libraries/data-binding/index.html?hl=ja#studio_support

findViewByIdをぶっとばせ

今回はサンプルとして,Hello worldを表示しているアプリを少しいじって,INABAボタンだけがあるだけのアプリを作成しました.
ここでは,INABAボタンにテキストをセットするところまでやります.

まず,レイアウトファイルを編集します.
サンプルファイルを以下に示しておきます.

// activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.example.shin.test.model.User"/>
    </data>

    <RelativeLayout xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.shin.test.MainActivity">

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"/>
    </RelativeLayout>
</layout>

やったこととしては,
1. レイアウトファイルのルートを<layout>
2. Bindさせたいデータオブジェクトを<data>で宣言する  - typeが型で,nameは変数名
3. Bindさせたい場所に@{}構文でセット

BindさせるデータオブジェクトはUserとして作りました.

// User.java
public class User{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

次に,ActivityでBindingオブジェクト取得してみましょう.

// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding mActivityMainBinding;
    private User mUser1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        mUser1 = new User();
        mUser1.setName("inaba");
        mActivityMainBinding.setUser(mUser1);
    }
}

mActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); でレイアウトとBindされたオブジェクトを得ることができる.
このオブジェクトのクラス名のルールとしては, レイアウトファイル名の_を抜いてパスカルケースで単語を連ね,末尾にBindingがつく.

mActivityMainBinding.setUser(mUser1);で Bindingオブジェクトとレイアウトファイルの<data>タグ内で宣言されているデータオブジェクトと紐付ける.

ここでButtonのViewを取ってきたいときは,findViewById + キャストでなく,以下のようにしてとれる.

Button button = mActivityMainBinding.button;

(これが一番うれしい点!!)

ここまでで,ボタンにテキストをいれるとこまでできた.
f:id:enter178:20161225180918p:plain

オブジェクト監視

次にINABAボタンを押したら,MATSUMOTOボタンに変化するようにしてみよう.
普通にやるとしたら,ButtonオブジェクトにClickListenerをセットして,setTextすることになると思う.

Data Bindingで実現するには,先程作ったUserオブジェクトの変化を監視できるようにし,Bindingオブジェクトに通知してあげる必要がある.

まず,Userクラスを監視できるようにするにはBaseObservableを継承し,監視するフィールドのゲッターに@Bindableをつける. 変更をBindingオブジェクトに通知するため,notifyPropertyChanged(BR.name); を監視するフィールドのセッターで呼んであげる.これでOK.

public class User extends BaseObservable{
    private String name;
    
    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

監視の設定がおわったので,ボタンが押された時の動作を記述する.

// activity_main.xml
 <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:onClick="@{activity.onNameClick}"/>

Buttonにandroid:onClick="@{activity.onNameClick}"/>のよう,onClick属性を追加し,
onNameClickメソッドを定義しておく.

// MainActivity.java
    public void onNameClick(View view){
        Toast.makeText(this, "name click", Toast.LENGTH_SHORT).show();
        mUser1.setName("matsumoto");
    }
}

これで完成! 基本的な使い方はこれで

参考

Android Data Binding低コスト導入 | TECH Projin