Android M の新機能!データバインディングを使ってみた

Android

データバインディングライブラリが公開

Google I/O 2015 で Android M が発表され、Chrome Tabs や 指紋認証、Google Pay、アクセス許可などさまざまな新機能が発表されました。楽しみですね!

今回はその中でも面白そうな新機能「データバインディング」を使ってみました。データバインディングはその名の通りデータをバインドしてくれる機能で、クラスのオブジェクトの状態の変更に応じて、XML に書いた View のプロパティを変更してくれます。

Android Studio 1.3 Developer Preview のインストール

まずは Android Studio 1.3 の Developer Preview をインストールしましょう。以下の Web ページ通りに行います。

日本語で書くとざっくり次のとおりです。

  1. Android Studio 1.2.2 をダウンロードする
  2. Settings を開き Appearance & Behavior > System Settings > Updates を開く
  3. チャンネルを Canary Chanel に変更する
  4. アップデートのチェックを行い、1.3 Developer Preview をインストールする

DataBinding ライブラリをインポートする

次に DataBinding ライブラリを Android アプリプロジェクトにインポートしましょう。まずプロジェクト直下の build.gradle を以下のようにします。公式ページ通りやったら動かなかったので、Gradle のバージョン指定に注意です。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0-beta1'
        classpath "com.android.databinding:dataBinder:1.0-rc0"
    }
}
allprojects {
    repositories {
        jcenter()
    }
}

次にアプリの Module のほうの build.gradle を以下のようにします。ここでの注意点は compileOptions です。これも無いと動きませんでした。

apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'

android {
    compileSdkVersion 'android-MNC'
    buildToolsVersion "23.0.0 rc1"

    defaultConfig {
        applicationId "YOUR_PROJECT_NAME"
        minSdkVersion 'MNC'
        targetSdkVersion 'MNC'
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Sync して終わりです。

XML を書く

次にいよいよ実装です。ウィザードで作成された直後のプロジェクトで作成される activity_main.xml を以下のようにします。

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="user" type="jp.classmethod.sample.User"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:text="@{user.firstName}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/button"
            android:text="ばいんど!"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

</layout>

ここで新しい書き方の登場です!いままでは XML のルートは View でしたが、それより大きな枠でもう1つ layout という階層が増えました。その中に data を入れ、variable にバインド対象のメンバーとクラスを指定しています。

なお、私の環境では XML での記述で新しい Attribute の解析エラーが出たので、Lint を無効化しました。

android-m-data-binding01

バインド対象のクラスを作成する

次に、バインド対象のクラスを作成しましょう。今回はサンプル通りに User クラスを作成しました。

package jp.classmethod.sample;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

public class User extends BaseObservable {
    private String firstName;
    private String lastName;
    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    @Bindable
    public String getFirstName() {
        return this.firstName;
    }
    @Bindable
    public String getLastName() {
        return this.lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
    }
}

バインド可能なクラスを作成するには BaseObservable を継承します。そしてゲッターに @Bindable アノテーションを付けます。すると同パッケージに BR クラスが自動で作成されるので、今度はセッターで notifyPropertyChanged メソッドを呼び出し、どのプロパティが変化したか通知します。

次に MainActivity.java を次のように実装します。

package jp.classmethod.sample;

import android.app.Activity;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import jp.classmethod.sample.databinding.ActivityMainBinding;

public class MainActivity extends Activity implements View.OnClickListener {

    private User mUser;
    private ActivityMainBinding mBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        this.mUser = new User("Test", "User");
        this.mBinding.setUser(this.mUser);
        findViewById(R.id.button).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        this.mUser.setFirstName("Hoge");
    }

}

ここでのポイントは大きく2点。1点目は ActivityMainBinding のクラスが <パッケージ名>.databinding の中に自動生成される点です。ここは恐らくコードヒントが出てこないので自分で書きましょう。2点目が DataBindingUtil を使って ActivityMainBinding クラスを生成するところです。第2引数で渡したレイアウト XML の Binding クラスが生成されます。レイアウト XML には data の中の variablenameuser としているため setUser() が自動生成されています。

ここまで実装してお気づきの人も居るかと思いますが、ちょいちょいエラーになります。

android-m-data-binding02

しかし、最大の注意点はエラーが表示されていてもコンパイルが成功するという点です! Developer Preview だからだと思いますが、エラーが表示されていても気にせずにビルドを実行してみてください。

以上で完成です!動かしてみると、ボタンを押したタイミングでテキストが更新されると思います。

android-m-data-binding

まとめ

簡単ですが、データバインディングの事始めでした。エラーが出てしまうところは Developer Preview だからでしょうか、、

他にもデータバインディングに関する沢山の機能が追加されているので、今後も試していきたいと思います!