AndroidでDataBindingのサンプルを調べていると、bindingオブジェクトにlifecycleOwnerを設定しているサンプルと設定していないサンプルがあって、何が違うの?要るの?要らないの?と疑問に思ったので確認しました。
目次
いきなり結論
Binding式にLiveDataを使っている場合は、lifecycleOwnerを設定する必要があります。
lifecycleOwnerを設定しないと、LiveDataの変更がViewに伝わらないとのこと。以下はAndroid DeveloperのViewDataBinding#setLifecycleOwner()
の説明の引用です。
Sets the
https://developer.android.com/reference/android/databinding/ViewDataBinding#setlifecycleownerLifecycleOwner
that should be used for observing changes of LiveData in this binding. If aLiveData
is in one of the binding expressions and no LifecycleOwner is set, the LiveData will not be observed and updates to it will not be propagated to the UI.
そもそもの疑問点(binding.lifecycleOwnerって?)
下記のようなDataBindingの初期化のサンプルコード、よくあると思います。Webでサンプルを探すと、bindingオブジェクトにlifecycleOwnerを設定しているサンプルとしていないサンプルがあり、削除してみても一見動作に問題がないように思えたりしたので、本当に必要なのか、何のために設定しているのか気になりつつ、よくわからないまま一応書いておいたりしていました。
class SampleFragment: Fragment() {
private lateinit var binding: FragmentSampleBinding
private val viewModel: SampleViewModel by sharedViewModel()
override fun onCreateView(
inflater: LayoutInflater,container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentSampleBinding.inflate(inflater, container, false)
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner // ←必要???
}
}
いい加減よくわからないまま放置するのはだめだなと思って調べたところ、上記の通りLiveDataをバインディングしている場合はlifecycleOwnerを設定する必要があるとのことでした。
LiveDataをバインディングってどういうこと?
LiveDataをバインディングするというのはどういう状態でしょうか。上記のSampleFragment
のレイアウトXMLとViewModelの例も書いてみます。
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="viewModel"
type="com.sample.SampleViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:text="@{viewModel.text}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
TextViewにSampleViewModel#text
をバインディングしています。SampleViewModelのソースコードは下記のようになります。
class SampleViewModel: ViewModel() {
val text = MutableLiveData<String>()
...
}
text
はMutableLiveData
で定義されています。これによりtext
プロパティの値を変更するだけでTextViewの表示が更新されることになるのですが、そのためには上記の通りlifecycleOwner
を設定する必要があるということです。
lifecycleOwnerの設定が不要なケース
上記の例で、Viewの初期化後にtext
の値を動的に変更しない場合、lifecycleOwner
を設定する必要はありません。(その場合はLiveDataである必要もないかもしれません。)
また、text
の値が動的に変わる場合であっても、そのたびに別の方法でViewの再描画処理が走るような場合もlifecycleOwner
の設定は不要です。これは例えば、RecyclerViewの各行のViewにDataBindingを使っていて、データソースが更新されると表示内容も変化するものの、RecyclerViewのAdapterに対してnotifyDataSetChanged()
のような通知が送られ、RecyclerView側の仕組みでViewが再描画されるような場合が当てはまります。
まとめ
結論をもう一度。
Binding式にLiveDataを使っている場合は、lifecycleOwnerを設定する必要があります。