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;
(これが一番うれしい点!!)
ここまでで,ボタンにテキストをいれるとこまでできた.
オブジェクト監視
次に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"); } }
これで完成! 基本的な使い方はこれで