Skip to content

Instantly share code, notes, and snippets.

@fleficher
Last active January 25, 2022 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fleficher/8759c4666aea291e281c2a1cbcc6c49a to your computer and use it in GitHub Desktop.
Save fleficher/8759c4666aea291e281c2a1cbcc6c49a to your computer and use it in GitHub Desktop.
Fragment View Binding Delegate
class FragmentAutoClearedValueBinding<T : ViewBinding>(
val binder: (View) -> T
) : ReadOnlyProperty<Fragment, T>,
DefaultLifecycleObserver {
private var value: T? = null
override fun onDestroy(owner: LifecycleOwner) {
value = null // Clear reference.
}
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
return value ?: binder(thisRef.requireView()).also {
setValue(thisRef, it)
}
}
private fun setValue(fragment: Fragment, value: T) {
fragment.viewLifecycle.removeObserver(this)
this.value = value
fragment.viewLifecycle.addObserver(this)
}
}
fun <T : ViewBinding> Fragment.viewBindingWithBinder(
binder: (View) -> T
) = FragmentAutoClearedValueBinding(binder)
@senpl
Copy link

senpl commented Oct 3, 2021

should it be fragment.lifecycle in newer kotlins ?

@RaoulNL
Copy link

RaoulNL commented Jan 24, 2022

Not entirely sure about that. (I use kotlin 1.6.10.)

When I use the lifecycle instead of viewLifeCycle, the code does compile.
Bit it seems the onDestroy method is never called. And when you have two fragments on a stack and press the back button, the bindings are missing on the first fragment. The fragment could not go through onDestroy if it comes back from the back-stack.

So it seems this solution might not work as intended. Does anyone have an idea for this?

@dav-true
Copy link

@RaoulNL seems like you can use fragment.viewLifecycleOwner.lifecycle. Try that

@RaoulNL
Copy link

RaoulNL commented Jan 25, 2022

@dav-true indeed, that solves the problem!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment