Fix lifecycle handling bug (#3319)

Fragments can go `onCreate` -> `onCreateView` -> `onViewCreated` -> `onDestroyView` without transitioning through `onStart`.

The previous code assumed `onStart` was always called. 

Se https://itnext.io/an-update-to-the-fragmentviewbindingdelegate-the-bug-weve-inherited-from-autoclearedvalue-7fc0a89fcae1
This commit is contained in:
Nik Clayton 2023-02-25 21:06:22 +01:00 committed by GitHub
parent c6f7ecdb5b
commit 4a0251800d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -28,23 +29,26 @@ class FragmentViewBindingDelegate<T : ViewBinding>(
private var binding: T? = null private var binding: T? = null
init { init {
fragment.lifecycle.addObserver( fragment.lifecycle.addObserver(object : DefaultLifecycleObserver {
object : DefaultLifecycleObserver { val viewLifecycleOwnerLiveDataObserver =
override fun onCreate(owner: LifecycleOwner) { Observer<LifecycleOwner?> {
fragment.viewLifecycleOwnerLiveData.observe( val viewLifecycleOwner = it ?: return@Observer
fragment
) { t -> viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
t?.lifecycle?.addObserver( override fun onDestroy(owner: LifecycleOwner) {
object : DefaultLifecycleObserver { binding = null
override fun onDestroy(owner: LifecycleOwner) { }
binding = null })
}
}
)
}
} }
override fun onCreate(owner: LifecycleOwner) {
fragment.viewLifecycleOwnerLiveData.observeForever(viewLifecycleOwnerLiveDataObserver)
} }
)
override fun onDestroy(owner: LifecycleOwner) {
fragment.viewLifecycleOwnerLiveData.removeObserver(viewLifecycleOwnerLiveDataObserver)
}
})
} }
override fun getValue(thisRef: Fragment, property: KProperty<*>): T { override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
@ -58,7 +62,7 @@ class FragmentViewBindingDelegate<T : ViewBinding>(
throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed.") throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed.")
} }
return viewBindingFactory(thisRef.requireView()).also { this@FragmentViewBindingDelegate.binding = it } return viewBindingFactory(thisRef.requireView()).also { this.binding = it }
} }
} }