MVVM 完全に理解した - 5
お待ちかね Two-way data binding(双方向バインディング) です。
Two-way data binding | Android Developers
ホントは一つ前の Bind layout views to Architecture Components についても書いてみたいところですが、そろそろ双方向バインディングも書かないとなので。
双方向バインディング
まず単方向バインディングの場合。
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@{viewmodel.rememberMe}" android:onCheckedChanged="@{viewmodel.rememberMeChanged}" />
checked
という値と onCheckedChanged
という値変更のイベントを別々に記述しなければなりませんでした。
一方、双方向バインディングの場合、
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@={viewmodel.rememberMe}" />
@={}
という表記法( notation )により、プロパティのデータ変更の受信と View の更新処理を1行で記述することができます。
動作的には、値の更新と同時に、View の更新をおこなってくれます。
(語彙力がない。)
実装
In order to react to changes in the backing data, you can make your layout variable an implementation of Observable, usually BaseObservable, and use a @Bindable annotation, as shown in the following code snippet:
実装するには、
- Data binding layout file を作成
Observable
やBaseObservable
と、@Bindable
アノテーションを使いこなす
とのこと。Observable
インターフェースは無いですが、BaseObservable
は前回の
MVVM 完全に理解した - 4 - 日々是好日
にて議論しているので、実装例を見てみます。
ちなみに Observable
インターフェースは、Observer パターンの Subject
クラスとほぼ同じ機能を持ちます。
Observable | Android Developers
class LoginViewModel : BaseObservable { // val data = ... @Bindable fun getRememberMe(): Boolean { return data.rememberMe } fun setRememberMe(value: Boolean) { // Avoids infinite loops. if (data.rememberMe != value) { data.rememberMe = value // React to the change. saveData() // Notify observers of a new value. notifyPropertyChanged(BR.remember_me) } } }
ログイン情報が端末に残っているかどうかのクラスみたいですね。
データを保存して、notifyPropertyChanged
メソッドにより値の更新を通知しています。
個人的には「通知」というよりも「発報」という感覚ですが。
双方向を行う上での注意点
PEAKS(ピークス)|Android アプリ設計パターン入門より、双方向バインディングを使う上での注意点を引用します。
ViewModel は Fragment(≒ View)がどのような状態かは関知しません。この単方向の原則は MVVM パターンでは大変重要です。お互いの状態を気にすると相互依存してコードが複雑になるためです(特に View の状態が複雑になります。)。
「双方向」といっているので View と ViewModel が相互に参照し合う形を想像するかもしれません。これはギルティ。
- View から ViewModel を参照、メソッドコール → ○
- ViewModel から View を参照、値更新 → ギルティ
ViewModel#setxxx
メソッドでnotifyPropertyChanged
をコールしてバインドした View に通知 → ○
蛇足
Bind layout views to Architecture Components | Android Developersより引用。
In Android Studio version 3.1 and higher, you can replace observable fields with LiveData objects in your data binding code.
とゆーわけで、ObservableField
は LiveData
にリプレースできまぁす!!なぜ 3.1 以上かの理由はご存じないです(諦)!!←
所感
Data Binding は学習コスト高いという指摘を見かけますが、たしかにしんどい。
とりあえずこれで準備は整ったので、アプリの概要をこれから考えます。←