Hey guys, I wrote my own view binder delegate. The...
# android
c
Hey guys, I wrote my own view binder delegate. These seem to be touchy with memory management, so can you let me know if it has any issues?
Copy code
class 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