Android LiveDataの2-way バインディングが動かなくて2日潰した
- 2018.10.09
- data-binding
- Android, LiveData
久しぶりにAndroidの最新技術をキャッチアップ中です。
RxJavaやKotlin、Architecture components、AndroidXなどなど。まだまだ新しい物が増えているようです。。
まず、自分のアプリにRxJava(RxKotlin)を導入しています。また、なんちゃってMVVMだったのですが、最近はAndroidがViewModelを採用しているようなので、最新のデファクタに寄せてみようと思ってました。
早速詰まったのが、LiveDataの2wayバインディング。いままではDataBindingを利用していたのですが、ViewModelとは、LiveDataが相性がいい模様。さらにAndroid Studio 3.1(?)から、DataBindingとLiveDataが連携できるようになったとのこと。
早速、バインディングしてみたのですが1wayはうまくいくのですが、2wayが動かないです。どのようなUIかというと、単純なEditTextとButtonがあって、EditTextが空でなければ、Buttonがenabled=true。空の場合、enabled=falseとしたいのです。
RxJavaの不慣れとあわせて、ここで2日も潰すはめに。。。
レイアウトイメージは、シンプルにこんな感じ
<layout> <!-- 中略 --> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/edit" android:text="@{viewModel.text}" android:lines="1" android:hint="テキストを入力してください" android:inputType="text"/> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更新" android:id="@+id/button" android:onClick="@{viewModel::onClick}" android:enabled="@{safeUnbox(viewModel.canUpdate)}"/> <!-- 以下略 -->
ViewModelはこんな感じです。書き換えているので、コンパイルなどは気にしてません。
class MyViewModel: ViewModel() { var text: MediatorLiveData<String> = MediatorLiveData() val canUpdate = MediatorLiveData<Boolean>() private fun isCanUpdate(): Boolean { val t = text.value return t != null && t.isNotEmpty() } init { // textと連動するように変更 canUpdate.addSource(text) { canUpdate.value = isCanUpdate() } }
さて、なぜ動かないのか。。。
結論は公式ドキュメントをちゃんと読みなさいということです。
The @={}
notation, which importantly includes the “=” sign, receives data changes to the property and listen to user updates at the same time.
この辺の新しい技術は公式ドキュメントのバージョン管理もわけわからないことになっているのですが、ちゃんと読みましょう。
普通のバインディングは@{xxx}としますが、2wayにしたい場合は@={xxx}と=(イコール)が必要です。なんかもっとわかりやすい表記にしてくれたらいいのに、、、。
-
前の記事
IntelliJで「Selected directory is not a valid home for JDK」 2018.07.22
-
次の記事
Firebase Authenticationでクラッシュ(iOS) 2019.01.03