initliaze 并通过 kotlin 延迟委托使用视图绑定视图,使视图在第一次膨胀后无法正确膨胀

问题描述

所以我正在将我的代码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