原来Kotlin的代理模式能让 viewBinding 变得优雅且简洁

336 阅读1分钟

背景

ViewBinding 集成在项目后,每次都需要在 Activity 或者 Fragment 中声明ViewBinding 的模板代码, 有些小伙伴会选择把模板代码放在相关的基类完成,通过反射完成, 但是对于有代码洁癖的我来说,这点还是不太好接受, 虽然在项目中用过,但是一直在心里想找一个更优雅的方式,正好最近在看 kotlin 的代理, 把 by 的原理看了下,恰好其中的 lazy 就是其一个典型的应用,于是心里就想,应该也能利用这样的思想去优化一下 ViewBinding 的使用, 于是就有了下面的内容

声明 AppCompatActivity 的 扩展方法

inline fun <reified BindingT : ViewBinding> AppCompatActivity.viewBindings(
    crossinline bind: (View) -> BindingT
) = object : Lazy<BindingT> {

    private var initialized: BindingT? = null

    override val value: BindingT
        get() = initialized ?: bind(
            findViewById<ViewGroup>(android.R.id.content).getChildAt(0)
        ).also {
            initialized = it
        }

    override fun isInitialized() = initialized != null
}

使用:xxxAppCompatActivity.kt 中,binding by viewBindings(xxxActivityBinding::bind)

声明 Fragment 的 扩展方法

inline fun <reified BindingT : ViewBinding> Fragment.viewBindings(
    crossinline bind: (View) -> BindingT
) = object : Lazy<BindingT> {

    private var initialized: BindingT? = null

    private val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            initialized = null
        }
    }

    override val value: BindingT
        get() = initialized ?: bind(requireView()).also {
            viewLifecycleOwner.lifecycle.addObserver(observer)
            initialized = it
        }

    override fun isInitialized() = initialized != null
}

使用:xxxFragment.kt 中,`binding by viewBindings(xxxFragmentBinding::bind)

Ending

GitHub 地址