问题描述
所以我正在将我的代码从 Kotlin Synthetic
迁移到 ViewBinding
但是当我编写 ViewBinding
代码时,它的样板非常多,就像第一个将所有视图分配为 lateinit var
以使用它们在整个班级中,然后在 onViewCreated
中初始化这些视图,然后我使用 by lazy
委托来克服该问题,一切正常,但是当我尝试我的应用程序并且它基于 single-activity-architecture
时我从 Afragment
转到 BFragment
然后回到 AFragment
一些视图如(工具栏不显示其标题和抽屉图标和菜单)没有膨胀,我调试并意识到懒惰的委托导致这是因为它给出了第一次分配的值,而且变量也是不可变的 val
所以我认为这可能是导致问题的原因,所以我编写了自定义的可变惰性委托,但这无济于事,我也不知道是什么我正在做,请提出任何建议。
MutableLazyDelegate.kt
class MutableLazyDelegate<T>(val initializer: () -> T) : ReadWriteProperty<Any?,T> {
private object UNINITIALIZED_VALUE
private var value: Any? = UNINITIALIZED_VALUE
@Suppress("UNCHECKED_CAST")
override fun getValue(thisRef: Any?,property: KProperty<*>): T =
if (value == UNINITIALIZED_VALUE)
synchronized(this) {
if (value == UNINITIALIZED_VALUE) initializer().also {
value = it
} else value as T
}
else value as T
override fun setValue(thisRef: Any?,property: KProperty<*>,value: T) {
synchronized(this) {
this.value = value
}
}
}
fun <T> mutableLazy(initializer: () -> T) = MutableLazyDelegate(initializer)
AFragment
class AFragment : Fragment(R.layout.a_fragment) {
private val binding by viewBinding(AFragmentBinding::bind)
private var toolbar by mutableLazy { binding.toolbar }
....
}
FragmentViewBindingDelegate
class FragmentViewBindingDelegate<T : ViewBinding>(
val fragment: Fragment,val viewBindingFactory: (View) -> T
) : ReadOnlyProperty<Fragment,T> {
var binding: T? = null
init {
fragment.lifecycle.addobserver(object : DefaultLifecycleObserver {
val viewLifecycleOwnerLiveDataObserver =
Observer<LifecycleOwner?> {
val viewLifecycleOwner = it ?: return@Observer
viewLifecycleOwner.lifecycle.addobserver(object : DefaultLifecycleObserver {
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 {
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.binding = it }
}
}
fun <T : ViewBinding> Fragment.viewBinding(viewBindingFactory: (View) -> T) =
FragmentViewBindingDelegate(this,viewBindingFactory)
解决方法
您的情况的解决方案是放弃 mutableLazy 委托,而是使用访问器
private val toolbar: Toolbar get() = binding.toolbar
尽管在大多数情况下,我建议从分配给 val
的绑定变量中获取工具栏
override fun onViewCreated(...) {
super onViewCreated(...)
val binding = binding