package at.connyduck.pixelcat.util import android.view.LayoutInflater import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.viewbinding.ViewBinding import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty /** * https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c */ inline fun AppCompatActivity.viewBinding( crossinline bindingInflater: (LayoutInflater) -> T ) = lazy(LazyThreadSafetyMode.NONE) { bindingInflater(layoutInflater) } class FragmentViewBindingDelegate( val fragment: Fragment, val viewBindingFactory: (View) -> T ) : ReadOnlyProperty { private var binding: T? = null init { fragment.lifecycle.addObserver( object : DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { fragment.viewLifecycleOwnerLiveData.observe( fragment ) { t -> t?.lifecycle?.addObserver( object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { binding = null } } ) } } } ) } override fun getValue(thisRef: Fragment, property: KProperty<*>): T { val binding = binding if (binding != null) { return binding } val lifecycle = fragment.viewLifecycleOwner.lifecycle if (!lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed.") } return viewBindingFactory(thisRef.requireView()).also { this@FragmentViewBindingDelegate.binding = it } } } fun Fragment.viewBinding(viewBindingFactory: (View) -> T) = FragmentViewBindingDelegate(this, viewBindingFactory)