一、概述
扩展函数: 指在一个类上增加一种新的行为,甚至我们没有这个类代码的访问权限。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())
}
}
}