13
9

More than 3 years have passed since last update.

DataBindingとLiveDataのハマりどころ

Posted at

layoutとLiveDataをbindingする際のはまりどころとチェックポイントをまとめる。
公式ドキュメントや人の解説をしっかり読んでいる人なら、はまらないレベル。
が、たまに新規アプリを作ると、いつもはまる。

FragmentのlayoutにViewModelのメンバLiveDataをbindingする場合を例にする。

Bindingクラスが生成されないんだけど

FragmentXXXBindingが生成されないケース。

build.gradleに以下の記述をしているか?

android {
...
    dataBinding {
        enabled = true
    }
}

layout XMLのルートをにしているか

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>...</data>
    ...
</layout>

LiveDataが全くbindされないんだけど

LiveDataに設定した初期値すら、Viewに反映されないケース。

bindingクラスにlifecycleOwnerを設定しているか?

binding = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_xxx, container, false)
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner // Activityならthisを設定

双方向バインディングされないんだけど?

LiveDataの初期値はViewに反映されるが、Viewの変化してもLiveDataの値が変わらないパターン。

"@"の後に"="をつけ忘れていないか?

<!-- NG -->
<EditText
    ...
    android:text="@{viewModel.liveData}" />

<!-- OK -->
<EditText
    ...
    android:text="@={viewModel.liveData}" />

CoroutineのFlowをLiveDataに変換した時、値を取得してもnullなんだけど

こんなケース。

// Model層のIF
val boolChannel = ConflatedBroadcastChannel<Boolean>(false)
val boolFlow: Flow<Boolean> = boolChannel.asFlow()

...

// ViewModelの実装
val boolData = model.boolFlow.asLiveData()

fun foobar() {
    println(boolData.value) // null
}

ConflatedBroadcastChannelをasFlowとasLiveDataでLiveDataに変換した場合、そのLiveDataをobserveしないと値が取得できないらしい。
そもそもLiveDataをobserveしないならLiveDataにする意味なし。
LiveDataではなくFlowとして扱い、singleなりcolletなりで値を取得するのが適切。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9