chinwag-android/app/src/main/java/com/keylesspalace/tusky/util/ViewBindingExtensions.kt
Christophe Beyls a19540f0e4
Simplify and reduce overhead of lazy view binding in Fragments (#4269)
This reduces complexity of view binding inflation in Fragments, and also
reduces overhead (no `KProperty` objects need to be generated by the
compiler) by implementing `Lazy` instead of `ReadOnlyProperty`.

For a full explanation, see this [detailed blog
post](https://medium.com/@bladecoder/viewlifecyclelazy-and-other-ways-to-avoid-view-memory-leaks-in-android-fragments-4aa982e6e579).
2024-02-23 20:10:33 +01:00

51 lines
1.7 KiB
Kotlin

package com.keylesspalace.tusky.util
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
/**
* Original code: https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c
* Refactor: https://bladecoder.medium.com/viewlifecyclelazy-and-other-ways-to-avoid-view-memory-leaks-in-android-fragments-4aa982e6e579
*/
inline fun <T : ViewBinding> AppCompatActivity.viewBinding(
crossinline bindingInflater: (LayoutInflater) -> T
) = lazy(LazyThreadSafetyMode.NONE) {
bindingInflater(layoutInflater)
}
private class ViewLifecycleLazy<out T : Any>(
private val fragment: Fragment,
private val initializer: (View) -> T
) : Lazy<T>, LifecycleEventObserver {
private var cached: T? = null
override val value: T
get() {
return cached ?: run {
val newValue = initializer(fragment.requireView())
cached = newValue
fragment.viewLifecycleOwner.lifecycle.addObserver(this)
newValue
}
}
override fun isInitialized() = cached != null
override fun toString() = cached.toString()
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) {
cached = null
}
}
}
fun <T : ViewBinding> Fragment.viewBinding(viewBindingFactory: (View) -> T): Lazy<T> =
ViewLifecycleLazy(this, viewBindingFactory)