MVVM 完全に理解した - 4
前回、次は双方向バインディングと言いましたが、その前に Observable object というものをやらないとつながらないのでそちらを少しだけ。
今回はこちらのページから。
Work with observable data objects | Android Developers
Observable fields
前回は不変なデータを持つ data class をバインドしていましたが、普通は入力や処理に応じて表示を変化させることを想像すると思います。
そこで出てくるのが、Data Binding Library の ObservableField<T>
や他の Observablexxx
クラスです。
class User { var firstName = ObservableField<String>() var lastName = ObservableField<String>() var age = ObservableInt() ... }
ObservableField
や類似のクラスは、BaseObservable
を継承しており、また Observable
インターフェースを実装しています。
上記の User
クラスは、すべてのフィールド変数が Observable になっています。
まー実際どう使うのか見ちゃったほうが早いですかね。
ObservableField で View の更新
まずは xml に User
をバインドする。
<data> <variable name="user" type="User"/> </data> … <TextView android:text="@{user.firstName}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:text="@{user.lastName}" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
//バインドするクラス class User { private var firstName = ObservableField<String>() private var lastName = ObservableField<String>() private var age = ObservableInt() //set が呼ばれると、自動で紐付けられた View が更新される public changeName() { firstName.set("hoge") lastName.set("fuga") } }
set
メソッド呼ぶだけで View も更新されるのだから便利なものです。
一方で、この View の更新にはもうひとつ方法があり、User : BaseObservable
として継承する方法です。
BaseObservable を継承して View と連携
xml は上記と同じ。実装を見てみます。
//BaseObservable を継承する class User : BaseObservable() { //普通のフィールド変数 private var age = 17 //Bindable アノテーション! @get:Bindable var firstName : String = "foo" set(value) { field = value notifyPropertyChanged(BR.firstName) } @get:Bindable var lastName : String = "bar" set(value) { field = value notifyPropertyChanged(BR.lastName) } }
setter について、BaseObservable#notifyPropertyChanged
をコールすることで、View の更新を行います。
また、急に出てきた BR
というやつ。notifyPropertyChanged)には次のように説明されています。
The getter for the property that changes should be marked with Bindable to generate a field in BR to be used as fieldId.
getter に Bindable
でマークすると、データバインディングに使用するための BR
っつーリソースを生成するよ(意訳)、と。
んで、BR
の ID はフィールド変数(と同じ名称?)を使用しているようです。
この ID を使用することで、なんのプロパティが更新されたか通知するようにしているとのこと。
所感
ただでさえ相互にやりとりするから混乱するのに、さらに2通りの方法とか作らないで欲しい件←
Data Binding は自動生成されるものが多くてよく分からなくなりますねー。公式リファレンスはよく読みませい₍₍(ง˘ω˘)ว⁾⁾
今回やっとプロパティに set
して更新する方法が出てきたので、次は双方向バインディング行けそうです。