Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Kotlin lazy implementation which automatically clears itself at appropriate times in the View Lifecycle, with a Fragment example
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
fun <T> Fragment.viewLifecycleLazy(initialise: () -> T): ReadOnlyProperty<Fragment, T> =
object : ReadOnlyProperty<Fragment, T>, DefaultLifecycleObserver {
// A backing property to hold our value
private var binding: T? = null
private var viewLifecycleOwner: LifecycleOwner? = null
init {
// Observe the View Lifecycle of the Fragment
this@viewLifecycleLazy
.viewLifecycleOwnerLiveData
.observe(this@viewLifecycleLazy, Observer { newLifecycleOwner ->
viewLifecycleOwner
?.lifecycle
?.removeObserver(this)
viewLifecycleOwner = newLifecycleOwner.also {
it.lifecycle.addObserver(this)
}
})
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
binding = null
}
override fun getValue(
thisRef: Fragment,
property: KProperty<*>
): T {
// Return the backing property if it's set, or initialise
return this.binding ?: initialise().also {
this.binding = it
}
}
}
class SomeFragment: Fragment(R.layout.some_fragment) {
val binding by viewLifecycleLazy { SomeFragmentBinding.bind(requireView()) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.someTextView.text = "Hello View Binding!"
}
}
@rishabhkohli

This comment has been minimized.

Copy link

@rishabhkohli rishabhkohli commented Aug 22, 2020

Great idea.
I rewrote it, trying to simplify it a bit.
https://gist.github.com/rishabhkohli/d4a4e49049b0a3578cb4347191a78de5

@Kaaveh

This comment has been minimized.

Copy link

@Kaaveh Kaaveh commented Dec 16, 2020

For those who have a problem with importing DefaultLifecycleObserver add this dependency:
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"

@gmk57

This comment has been minimized.

Copy link

@gmk57 gmk57 commented Jan 20, 2021

There is a catch: DefaultLifecycleObserver.onDestroy() is called before Fragment.onDestroyView(), so if you access binding from onDestroyView(), a new binding is created and cached. If later this fragment is restored from back stack, binding still points to that old view. We need to check current lifecycle state, see example here.

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