Kotlin基礎 — 擴充套件函式

Elson_6發表於2018-03-01

概述

擴充套件函式:指在一個類上增加一種新的行為,甚至我們沒有這個類程式碼的訪問許可權。類似Java中很多帶有static方法的工具類。

優勢:不需要在呼叫方法的時候把整個物件當作引數傳入。而是像是屬於擴充套件類的一樣,可以使用this關鍵字和呼叫所有public方法。


應用場景

參考anko-common 依賴包中ContextUtils、Dialogs 等檔案的寫法

// 屬性擴充套件
// 注意:anko-common包中沒有擴充套件V4包中的Fragment,需要自己擴充套件,否則無法獲取到ctx屬性
val Fragment.ctx: Context
    get() = activity

// 屬性擴充套件
val Context.ctx: Context
    get() = this

// 函式擴充套件
inline fun <reified T : View> Activity.find(id: Int): T = findViewById(id) as T
inline fun <reified T : View> Fragment.find(id: Int): T = view?.findViewById(id) as T

// 函式擴充套件
fun Context.toast(textResource: Int) = Toast.makeText(this, textResource, Toast.LENGTH_SHORT).show()
fun Context.toast(text: CharSequence) = Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
inline fun AnkoContext<*>.longToast(textResource: Int) = ctx.longToast(textResource)
// ...略...
複製程式碼

1. 屬性的擴充套件

val Fragment.ctx: Context
    get() = activity

public var TextView.text: CharSequence
    get() = getText()
    set(v) = setText(v)
複製程式碼

2. 函式的擴充套件

fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, duration).show()
}

複製程式碼

應用

擴充套件EditText的TextWatcher監聽

fun EditText.beforeTextChanged(action: (s: CharSequence?, start: Int, count: Int, after: Int)->Unit) = textWatch(before = action)

fun EditText.onTextChanged(action: (s: CharSequence?, start: Int, count: Int, after: Int)->Unit) = textWatch(change = action)

fun EditText.afterTextChanged(action: (s: Editable?)->Unit) = textWatch(after = action)


fun EditText.textWatch(
        before: ((s: CharSequence?, start: Int, count: Int, after: Int)->Unit)? = null,
        change: ((s: CharSequence?, start: Int, before: Int, count: Int)->Unit)? = null,
        after:  ((s: Editable?) -> Unit)? = null
) : EditText {

    return apply { // 這裡返回EditText
        val listener = object : TextWatcher{
            override fun afterTextChanged(s: Editable?) {
                after?.invoke(s)
            }

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

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

        }
        addTextChangedListener(listener)
    }
}
複製程式碼

使用

class JokeListFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater?.inflate(R.layout.joke_fragment_joke_list, null)
        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
       
        // 實現鏈式呼叫
        editText.beforeTextChanged {
            s, start, count, after -> Log.d("Joke", "before =$s")

        }.onTextChanged {
            s, start, count, after -> Log.d("Joke", "change =$s")

        }.afterTextChanged {
            s -> 
            Log.d("Joke", "after =${s.toString()}")
            toast(s.toString())
        }
    }

}

複製程式碼

相關文章