Data(View)Bindingのベストプラクティス

1 min read読了の目安(約1500字

業務のコードレビュー中に気になるロジックがあり質問したところ勉強になったので、参考になる人もいるかもと思い記事化
公式サイトを見てもらうとそのままの内容です。

実際のコード

private var _binding: MainFragmentBinding? = null
private val binding get() = _binding!!

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    _binding = MainFragmentBinding.bind(view)
    binding.message.setText("AAA")
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

↑公式だとonCreateViewでBinding#inflateを呼んでいるので、そちらの方が無難なのかもしれません

これまで自分で書く場合はこのような書き方をしていました。

private lateinit var binding: MainFragmentBinding

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding = MainFragmentBinding.bind(view)
}

結論

上記コードの重要な違いとしてはonDestroyViewでnullをセットしているかどうかがメインになります。

生存時間の短いViewの参照をより生存期間の長いFragmentが持つ事でメモリが解放されない事を防ぐためにonDestroyViewにて参照をクリアすることが推奨されています。

また、公式のサンプルコードを見ると以下の文言があります。
Consider not storing the binding instance in a field, if not needed.
英語は苦手なのでよく分かりませんが、不要ならばbindingインスタンスはクラス変数に入れない方が良いと言ってる気がします。

なので、Data(View)Bindingを利用する時は

  • bindingインスタンスは最小限のスコープで使う
  • Fragmentでbinding変数を宣言した場合はonDestroyViewにてnullをセットする
    のが良さそうです。

追記(2021/1/15

DataBinding-ktxを使うと何も気にしないでいいので便利です。