| package com.airbnb.lottie.samples.utils |
| |
| import android.os.Handler |
| import android.os.Looper |
| import android.view.View |
| import androidx.fragment.app.Fragment |
| import androidx.lifecycle.Lifecycle |
| import androidx.lifecycle.LifecycleObserver |
| import androidx.lifecycle.OnLifecycleEvent |
| import androidx.viewbinding.ViewBinding |
| import kotlin.properties.ReadOnlyProperty |
| import kotlin.reflect.KProperty |
| |
| /** |
| * Create bindings for a view similar to bindView. |
| * |
| * To use, just call |
| * private val binding: FHomeWorkoutDetailsBinding by viewBinding() |
| * with your binding class and access it as you normally would. |
| */ |
| inline fun <reified T : ViewBinding> Fragment.viewBinding() = FragmentViewBindingDelegate(T::class.java, this) |
| |
| class FragmentViewBindingDelegate<T : ViewBinding>( |
| bindingClass: Class<T>, |
| val fragment: Fragment |
| ) : ReadOnlyProperty<Fragment, T> { |
| private val clearBindingHandler by lazy(LazyThreadSafetyMode.NONE) { Handler(Looper.getMainLooper()) } |
| private var binding: T? = null |
| |
| private val bindMethod = bindingClass.getMethod("bind", View::class.java) |
| |
| init { |
| fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> |
| viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver { |
| @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) |
| fun onDestroy() { |
| // Lifecycle listeners are called before onDestroyView in a Fragment. |
| // However, we want views to be able to use bindings in onDestroyView |
| // to do cleanup so we clear the reference one frame later. |
| clearBindingHandler.post { binding = null } |
| } |
| }) |
| } |
| } |
| |
| @Suppress("UNCHECKED_CAST") |
| override fun getValue(thisRef: Fragment, property: KProperty<*>): T { |
| binding?.let { return it } |
| |
| val lifecycle = fragment.viewLifecycleOwner.lifecycle |
| if (!lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { |
| error("Cannot access view bindings. View lifecycle is ${lifecycle.currentState}!") |
| } |
| |
| binding = bindMethod.invoke(null, thisRef.requireView()) as T |
| return binding!! |
| } |
| } |