Cole K
10/14/2021, 4:22 AMclass FragmentViewBinder {
private lateinit var bindingReference: BindingReference<ViewBinding>
fun inflate(inflater: LayoutInflater, viewGroup: ViewGroup?): View {
val binding = bindingReference.inflate(inflater, viewGroup, false)
return binding.root
}
fun <V : ViewBinding> bind(inflateViewBinding: InflateViewBinding<V>): ReadOnlyProperty<Fragment, V> {
bindingReference = BindingReference(inflateViewBinding)
return FragmentViewBindingDelegate(bindingReference) as ReadOnlyProperty<Fragment, V>
}
}
private class FragmentViewBindingDelegate<V : ViewBinding>(private val bindingReference: BindingReference<V>) : ReadOnlyProperty<Fragment, V> {
private var observing = false
override fun getValue(thisRef: Fragment, property: KProperty<*>): V {
val binding = bindingReference.binding ?: throw IllegalStateException("Binding accessed, but it is null. Has inflate been called?")
if (!thisRef.isInitialized) throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed")
if (!observing) bindingReference.registerUnbinder(thisRef)
return binding
}
private val Fragment.isInitialized: Boolean
get() {
val lifecycle = viewLifecycleOwner.lifecycle
val currentState = lifecycle.currentState
return currentState.isAtLeast(Lifecycle.State.INITIALIZED)
}
}
private class BindingReference<V : ViewBinding>(_inflate: InflateViewBinding<V>) {
var binding: V? = null
var inflate: InflateViewBinding<V> = { inflater, viewGroup, attachToParent ->
binding = _inflate(inflater, viewGroup, attachToParent)
binding!!
}
fun registerUnbinder(fragment: Fragment) {
fragment.parentFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentLifecycleCallbacks() {
override fun onFragmentDestroyed(fm: FragmentManager, f: Fragment) {
super.onFragmentDestroyed(fm, f)
binding = null
}
}, false)
}
}
private typealias InflateViewBinding<V> = (LayoutInflater, ViewGroup?, Boolean) -> V