[Android] DataBinding-ktx 3.0.1 をリリースしました
追記: DataBinding-ktx 4.0.0 をリリースしました
・・・
DataBinding-ktx とは
DataBinding と ViewBinding に関する問題を解決し、安全・簡単に利用するためのライブラリです。
DataBinding/ViewBinding に関する問題
1. Activity と Fragment で変数宣言の方法が異なる
Activity では by lazy を使えますが、
Fragment では BackStack や Attach/Detach を使う場合は View が再生成されるので by lazy が使えません(*)。
※: 再生成後の View に対して binding インスタンスが生成されないため
2. setLifecycleOwner を呼び出し忘れる
DataBinding のみの問題ですが、LiveData を利用している場合、setLifecycleOwner を呼び出さないと LiveData が DataBinding されません。
DataBinding-ktx による解決
1. Activity と Fragment で変数宣言の方法が異なる
Kotlin の Delegated Properties によって Activity と Fragment で同じ書き方でプロパティを宣言することができます。
2. setLifecycleOwner を呼び出し忘れる
binding 変数に初回アクセス時に自動的に setLifecycleOwner が呼び出されているため呼び出し忘れがなくなります。
DataBinding-ktx の使い方
DataBinding
Activity
class MainActivity : AppCompatActivity() {
private val binding: MainActivityBinding by dataBinding(R.layout.main_activity)
}
Fragment
class MainFragment : Fragment() {
private val binding: MainFragmentBinding by dataBinding(R.layout.main_fragment)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return binding.root
}
}
ViewBinding
Activity
class MainActivity : AppCompatActivity() {
private val binding: MainActivityBinding by viewBinding()
}
Fragment
class MainFragment : Fragment() {
private val binding: MainFragmentBinding by viewBinding()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return binding.root
}
}
DataBinding-ktx 3.0.1 について
onDestroyView で binding を安全に使用可能
binding は内部的に lazy で実装されています。Fragment は View の再生成があるため、onDestroyView で binding に null を設定しています。しかし、 実際の設定タイミングは onDestroyView の直前でした。onDestroyView で binding を使用した場合、binding が null になっているので再度 inflate されて binding がその後 null に設定されることがないためメモリリークします。(下記参照)
fun <T : ViewDataBinding> Fragment.dataBinding(@LayoutRes layoutResId: Int): Lazy<T> {
return object : Lazy<T> {
private var binding: T? = null
override fun isInitialized(): Boolean = binding != null
override val value: T
get() = binding ?: inflate<T>(this@dataBinding, layoutResId).also {
binding = it
viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroyView() {
viewLifecycleOwner.lifecycle.removeObserver(this)
binding = null // Called before onDestroyView!
}
})
}
}
}
DataBinding-ktx 3.0.1 では、binding に null を設定するタイミングを onDestroyView の直後に修正しました。そのため、onDestroyView で binding を使用しても inflate されず、onDestroyView 後は binding が null になるため、メモリリークしなくなりました。
DataBinding-ktx 3.0.1 はこちら
ここから先は
¥ 100
この記事が気に入ったらサポートをしてみませんか?