通过 kotlin lazy delegate 初始化和使用视图绑定视图,使视图在第一次膨胀后无法正确膨胀

initliaze and use viewbinding views by kotlin lazy delegate making view making view not inflate properly after first inflate

所以我正在将我的代码从 Kotlin Synthetic 迁移到 ViewBinding,但是当我编写 ViewBinding 代码时,它的样板太多了,就像第一个将所有视图分配给 lateinit var 一样在整个 class 中使用它们,然后在 onViewCreated 中初始化这些视图,然后我使用 by lazy 委托来解决这个问题,一切正常,但是当我尝试我的应用程序时,它是 single-activity-architecture 基于所以当我从 AfragmentBFragment 然后回到 AFragment 一些视图(工具栏不显示其标题和抽屉图标和菜单)没有膨胀并且我调试并意识到导致此问题的惰性委托是因为它给出了 first-time 分配的值并且变量也是不可变的 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