DataBindingオブジェクトにlifecycleOwnerを設定する理由

AndroidでDataBindingのサンプルを調べていると、bindingオブジェクトにlifecycleOwnerを設定しているサンプルと設定していないサンプルがあって、何が違うの?要るの?要らないの?と疑問に思ったので確認しました。

いきなり結論

Binding式にLiveDataを使っている場合は、lifecycleOwnerを設定する必要があります。

lifecycleOwnerを設定しないと、LiveDataの変更がViewに伝わらないとのこと。以下はAndroid DeveloperのViewDataBinding#setLifecycleOwner()の説明の引用です。

Sets the LifecycleOwner that should be used for observing changes of LiveData in this binding. If a LiveData 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.

https://developer.android.com/reference/android/databinding/ViewDataBinding#setlifecycleowner

そもそもの疑問点(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>()
    
    ...
}

textMutableLiveDataで定義されています。これによりtextプロパティの値を変更するだけでTextViewの表示が更新されることになるのですが、そのためには上記の通りlifecycleOwnerを設定する必要があるということです。

lifecycleOwnerの設定が不要なケース

上記の例で、Viewの初期化後にtextの値を動的に変更しない場合、lifecycleOwnerを設定する必要はありません。(その場合はLiveDataである必要もないかもしれません。)

また、textの値が動的に変わる場合であっても、そのたびに別の方法でViewの再描画処理が走るような場合もlifecycleOwnerの設定は不要です。これは例えば、RecyclerViewの各行のViewにDataBindingを使っていて、データソースが更新されると表示内容も変化するものの、RecyclerViewのAdapterに対してnotifyDataSetChanged()のような通知が送られ、RecyclerView側の仕組みでViewが再描画されるような場合が当てはまります。

まとめ

結論をもう一度。

Binding式にLiveDataを使っている場合は、lifecycleOwnerを設定する必要があります。