[Android] DataBinding-ktx 3.0.1 Released
What is DataBinding-ktx
A library that solves problems related to DataBinding and ViewBinding, and is safe and easy to use.
DataBinding / ViewBinding issues
1. Variable declaration method is different between Activity and Fragment
By lazy can be used in Activity , but when using BackStack or Attach / Detach in Fragment’s view is regenerated, so by lazy cannot be used (*).
*: Because binding instance is not generated for the view after regeneration
2. Forget to call setLifecycleOwner
This is only a problem with DataBinding. When using LiveData, LiveData will not be binding unless setLifecycleOwner is called.
Solution with DataBinding-ktx
1. Variable declaration method is different between Activity and Fragment
Kotlin’s Delegated Properties allows you to declare properties in the same way in Activity and Fragment .
2. Forget to call setLifecycleOwner
The setLifecycleOwner is automatically called when you first access the binding variable, so you will never forget to call it.
How to use 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
}
}
About DataBinding-ktx 3.0.1
You can use binding safely in onDestroyView
binding is implemented internally as lazy. Since Fragment has regeneration of View, binding is set to null in onDestroyView. However, the actual setting timing was just before onDestroyView. When binding is used in onDestroyView, since the binding is null, it will be inflate again and the binding will not be set to null after that. (See below)
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!
}
})
}
}
}
In DataBinding-ktx 3.0.1, the timing for setting binding to null was corrected immediately after onDestroyView. For this reason, using binding in onDestroyView does not inflate, and after onDestroyView the binding is null, so there is no memory leak.