Kotlin 更加优雅的 Builder - 使用 with

借助 with 的神力

看到上一篇文章对 with 的解析,你是不是想到什么?with 简直就是为 Builder 模式而生的。

我们尝试构建一个 PopupWindow,下面是我们部分需要的东西(可自定义的参数):

context
layoudId
width
listener        //为popupWindow的某些view设置点击事件复制代码

我们的 Builder 类如下:

class PopupWindowGen (private val context: Context) {
    @LayoutRes
    var layoutId = 0
    var width = 100
    //设置监听器需要知道view的id和对应的响应事件,这里用 Pair 把他们包起来
    private val listeners: MutableListInt, (View) -> Unit>> = mutableListOf()

    fun addListener(@IdRes id: Int, body: (View) -> Unit) {
        listeners.add(Pair(id, body))
    }

    fun build(): PopupWindow {
        val popView = LayoutInflater.from(context).inflate(layoutId, null, false)
        listeners.forEach {
            val view = popView.findViewById(it.first)
            view.setOnClickListener { v -> it.second(v) }
        }
        val popupWindow = PopupWindow(popView, width, ViewGroup.LayoutParams.WRAP_CONTENT, true)
        return popupWindow
    }
}复制代码

这样,一个简单的 Builder 就编写完毕了,我们可以像下面一样构造出对象了:

val popupWindow = with(PopupWindowGen(context)) {
                    layoutId = R.layout.popup_window
                    width = 200
                    addListener(R.id.btn, { print(it) })
                    addListener(R.id.tvm { print(it) })
                    build()
                }复制代码

优化

我们发现其实上面代码还是有点怪怪的,我们想要的是:

val popupWindow = PopupWindowGen.generate(context) {
    ...
}复制代码

我们在 PopupWindowGen 里面再写一个静态方法,同时将构造方法私有化:

class PopupWindowGen (private val context: Context) {
    companion object {
        fun generate(context: Context, body: PopupWindowGen.() -> PopupWindow): PopupWindow {
            return with(PopupWindowGen(context)) {
                body()
            }
        }
    }
    ...
}复制代码

大功告成:

val popupWindow = PopupWindowGen.with(context) {
                    layoutId = R.layout.popup_window
                    width = 200
                    addListener(R.id.btn, { print(it) })
                    addListener(R.id.tvm { print(it) })
                    build()
                }复制代码

快动手试试吧~

———

技术上的问题,欢迎讨论。

最近在 Github 上维护的项目:

  • LiteWeather [一款用 Kotlin 编写,基于 MD 风格的轻量天气 App],对使用 Kotlin 进行实际开发感兴趣的同学可以看看,项目中会使用到 Kotlin 的委托机制、扩展机制和各种新奇的玩意。
  • LiteReader [一款基于 MD 的极轻阅读 App,提供知乎日报、豆瓣电影等资源],项目主要使用了 MVVM 设计模式,界面遵循 Material Design 规范,提供轻量的阅读体验。
  • LiveMVVM [Kotlin 编写的 Android MVVM 框架,基于 android-architecture],轻量 MVVM+Databinding 开发框架。
  • AnkoUtil [Kotlin 编写的 Android 扩展库]

欢迎 star/fork/follow 提 issue 和 PR。

你可能感兴趣的:(Kotlin 更加优雅的 Builder - 使用 with)