kotlin TextWatcher dsl优化,最简单分析理解

302 阅读1分钟

kotlin TextWatcher dsl优化,最简单分析理解

前提概念:带有接收者的函数类型

1.声明一个普通的函数

var block: (Int) -> Unit

2.声明一个带接收者的函数

var block2: Person.(Int) -> Unit

3.使用示例:

private fun test0(block: (Int) -> Unit) {
    block.invoke(1)
}

fun test() {
    test0 {
        //it 指向 1
        println()
    }
}

private fun test1(block2: Person.() -> Unit) {
    block2.invoke(Person("12",3))
}

fun test() {
    test1 {
        //this 指向 person
        println(this.name)
    }
}

private fun test2(person: Person, block2: Person.() -> Unit) {
    block2.invoke(person)
}

fun test() {
    test2(Person("123", 1)) {
        //this 指向 person
        println(this.name)
    }
}

总结
如果想简单的理解,可以将接收者作为函数的第一个参数进行带入理解,内部使用this。

TextWatchDsl 示例

typealias FunBeforeTextChanged = (s: CharSequence?, start: Int, count: Int, after: Int) -> Unit
typealias FunOnTextChanged = (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit
typealias FunAfterTextChanged = (s: Editable?) -> Unit

fun TextView.addTextChangedListenerDsl(block: TextWatchDsl.() -> Unit) {
    val textWatchDsl = TextWatchDsl()
    block.invoke(textWatchDsl)
    this.addTextChangedListener(textWatchDsl)
}

class TextWatchDsl : TextWatcher {

    var funBeforeTextChanged: FunBeforeTextChanged? = null
    var funOnTextChanged: FunOnTextChanged? = null
    var funAfterTextChanged: FunAfterTextChanged? = null

    fun beforeTextChanged(method: FunBeforeTextChanged?) {
        this.funBeforeTextChanged = method
    }

    fun onTextChanged(method: FunOnTextChanged?) {
        this.funOnTextChanged = method
    }

    fun afterTextChanged(method: FunAfterTextChanged?) {
        this.funAfterTextChanged = method
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        funBeforeTextChanged?.invoke(s, start, count, after)
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        funOnTextChanged?.invoke(s, start, before, count)
    }

    override fun afterTextChanged(s: Editable?) {
        funAfterTextChanged?.invoke(s)
    }

}

fun test(context: Context) {
    TextView(context).addTextChangedListenerDsl {
        //这里面只是存粹的函数调用,不要想太多,相当于把函数作为参数传递给 TextWatchDsl
        //所以才可以随意调用1个或者多个
        //同时合并起来也作为一个大的函数,触发点是在block.invoke里面
        //真正的实现,还是在 TextView.addTextChangedListener 里面
        beforeTextChanged { s, start, count, after ->
            println("$s, $start, $count, $after")
        }
        onTextChanged { s, start, before, count ->
            println("$s, $start, $before, $count")
        }
        afterTextChanged {
            println(it)
        }
    }
}

总结:

  1. kotlin dsl风格能够让代码更优雅,但是也会创建多个函数,这点要注意。
  2. dsl里面只是函数调用,要理解dsl需要去看从哪触发这个函数调用,以及接收者在哪创建的。