Skip to content

Instantly share code, notes, and snippets.

@nullptr2this
Last active May 3, 2022 18:36
Show Gist options
  • Save nullptr2this/a05be2b8dd24813c35f33db77f8d4b48 to your computer and use it in GitHub Desktop.
Save nullptr2this/a05be2b8dd24813c35f33db77f8d4b48 to your computer and use it in GitHub Desktop.
View Binding Holder for Fragments
import android.view.View
import androidx.viewbinding.ViewBinding
/**
* Creates a [ViewBindingHolder] with the given [ViewBinding] factory to
* act as an accessor to the [ViewBinding].
*
* ```
* class MyFragment : Fragment(R.layout.fragment_mine) {
*
* private val binding = viewBindingFrom(FragmentMineBinding::bind)
* private var counter: Int = 0
*
* override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
* super.onViewCreated(view, savedInstanceState)
* binding.bindTo(view)
* binding.views.buttonIncrement.setOnClickListener {
* counter += 1
* updateCounterDisplay()
* }
* }
*
* override fun onDestroyView() {
* super.onDestroyView()
* binding.clear()
* }
*
* private fun updateCounterDisplay() {
* binding.doWithViews {
* textCounter.setText("Counter: $counter")
* }
* }
* ```
*/
fun <T : ViewBinding> viewBindingFrom(factory: (View) -> T): ViewBindingHolder<T> {
return ViewBindingHolder(factory)
}
/**
* Wrapper around a [ViewBinding] intended to slightly reduce boiler plate
* when [ViewBinding]s are used in Fragments.
*/
class ViewBindingHolder<T : ViewBinding>(
private val factory: (View) -> T
) {
private var viewBinding: T? = null
/**
* Gets the view binding instance that has been bound to this holder instance.
*/
val views: T
get() = requireNotNull(viewBinding) { "The associated view binding does not exist." }
/**
* Executes the block provided with the view binding instance if it exists.
*/
fun doWithViews(block: T.() -> Unit) {
viewBinding?.let(block)
}
/**
* Binds a view binding instance from the View provided and returns the View
* as a convenience.
*/
fun bindTo(view: View): View {
viewBinding = factory.invoke(view)
return view
}
/**
* Frees the view binding instance so it and its associated views
* are not leaked.
*/
fun clear() {
viewBinding = null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment