Created
September 26, 2022 13:43
-
-
Save kikogassen/4061cc3578f4b38d4b2788ac0d91bac4 to your computer and use it in GitHub Desktop.
viewBinding delegate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle | |
import android.view.View | |
class CustomFragment : Fragment(R.layout.fragment_round_up_accounts) { | |
private val binding by viewBinding(FragmentCustomBinding::bind) | |
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
// Use binding here | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Handler | |
import android.os.Looper | |
import android.view.View | |
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 | |
private class FragmentViewBindingDelegate<T : ViewBinding>( | |
val fragment: Fragment, | |
val factory: (View) -> T | |
) : ReadOnlyProperty<Fragment, T>, DefaultLifecycleObserver { | |
private var binding: T? = null | |
private var waitingToDestroyBinding = false | |
override fun getValue(thisRef: Fragment, property: KProperty<*>): T { | |
alertIfNotOnMainThread() | |
if (waitingToDestroyBinding && | |
fragment.viewLifecycleOwner.lifecycle.currentState != Lifecycle.State.DESTROYED | |
) { | |
// Don't force clear binding if we're in the DESTROYED state | |
// so that binding can still be reused within Fragment.onDestroyView | |
binding = null | |
waitingToDestroyBinding = false | |
} | |
return binding ?: fragment.viewLifecycleOwner.lifecycle.run { | |
if (!currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { | |
error("Called before onCreateView or after onDestroyView.") | |
} | |
factory(thisRef.requireView()).also { | |
addObserver(this@FragmentViewBindingDelegate) | |
binding = it | |
} | |
} | |
} | |
override fun onDestroy(owner: LifecycleOwner) { | |
// Fragment.viewLifecycleOwner calls FullLifecycleObserver.onDestroy before | |
// Fragment.onDestroyView, so postpone clearing the value | |
alertIfNotOnMainThread() | |
waitingToDestroyBinding = true | |
Handler(Looper.getMainLooper()).post { | |
if (waitingToDestroyBinding) { | |
binding = null | |
waitingToDestroyBinding = false | |
} | |
} | |
} | |
private fun alertIfNotOnMainThread() { | |
if (BuildConfig.DEBUG) { | |
require(Looper.getMainLooper().isCurrentThread) { "Why aren't you on the main thread?" } | |
} | |
} | |
} | |
fun <T : ViewBinding> Fragment.viewBinding(factory: (View) -> T): ReadOnlyProperty<Fragment, T> = | |
FragmentViewBindingDelegate(this, factory) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment