kotlin DSL simple example

Case scenario

When too many interface methods, but we only need one method, for example TextView.addTextChangedListener, we just need it onTextChanged method

1. Original mode

tv.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable?) {
    }
    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
    }
    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        print("文字修改为:$s")
    }
})

Obviously, we here need to realize afterTextChanged empty and beforeTextChanged, a bit tedious

2. Empty the adapter mode

tv.addTextChangedListener(object : EmptyTextWatcher() {
    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        print("文字修改为:$s")
    }
})

This is actually very simple, is to add a middle class interface empty implementation of it, this is our normal operation, but in kotlin there, we can also have the following two high-level gameplay

open class EmptyTextWatcher : TextWatcher {
    override fun afterTextChanged(s: Editable?) {

    }

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

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

}

3. Higher-order functions the way

tv.addTextChangedListenerClosure(
    onTextChanged = { charSequence, start, after, count ->
        print("文字修改为:$charSequence")
    }
)

This is a method to expand the added inline addTextChangedListenerClosure, parameters are a function of this method

inline fun TextView.addTextChangedListenerClosure(
    crossinline afterTextChanged: (Editable?) -> Unit = {},
    crossinline beforeTextChanged: (CharSequence?, Int, Int, Int) -> Unit = { charSequence, start, count, after -> },
    crossinline onTextChanged: (CharSequence?, Int, Int, Int) -> Unit = { charSequence, start, after, count -> }
) {
    val listener = object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            afterTextChanged.invoke(s)
        }

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

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

4. DSL manner

tv.addTextChangedListenerDsl {
    onTextChanged { charSequence, start, after, count ->
        print("文字修改为:$charSequence")
    }
}

This then, is the first to pass through the expansion method init method body, inside the init method, initialize afterTextChanged and other functions, and then call the Save method in the callback function inside

fun TextView.addTextChangedListenerDsl(init: TextChangedListenerDsl.() -> Unit) {
    val listener = TextChangedListenerDsl()
    listener.init()
    this.addTextChangedListener(listener)
}

class TextChangedListenerDsl : TextWatcher {

    var afterTextChanged: ((Editable?) -> Unit)? = null

    var beforeTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null

    var onTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null

    /**
     * DSL方法
     */
    fun afterTextChanged(method: (Editable?) -> Unit) {
        afterTextChanged = method
    }

    fun beforeTextChanged(method: (CharSequence?, Int, Int, Int) -> Unit) {
        beforeTextChanged = method
    }

    fun onTextChanged(method: (CharSequence?, Int, Int, Int) -> Unit) {
        onTextChanged = method
    }

    /**
     * 原始方法
     */
    override fun afterTextChanged(s: Editable?) {
        afterTextChanged?.invoke(s)
    }

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

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

}

These are just a simple example DSL, mainly DSL demonstrate how to write, if you have a better use of DSL scene, welcome to add.

Guess you like

Origin blog.csdn.net/weixin_34062469/article/details/90783171