这是一篇辅助文章,为了辅助你们理解后面的文章,先前先简单的阐述下kotlin的DSL。java
DSL指的是特定领域语言,利用kotlin的DSL语言,咱们能够写成更加整洁的代码,是代码的可阅读行大幅度提高。基本的概念以及好处我就再也不重复阐述了,网上已经有不少相似的文章了,我就经过具体的代码示例进行展现好了。bash
我仍是从最多见EditText
的TextWatcher
提及。app
在Java
中当咱们须要添加文本输入监听的的时候,是以下的写法:ide
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
复制代码
可是每每有时,咱们只须要afterTextChanged
监听,并不须要其余两个,但因为接口的限制,咱们不得不所有写出将其实现。致使书写体验和阅读体验降低。性能
那么在kotlin
中咱们能够骚操做:学习
editText.onTextChange {
afterTextChanged { s ->
}
}
复制代码
确定有小伙伴,是这个表情:ui
那么这是如何实现的呢,首先,自定义个类,继承TextWatcher
:spa
class TextWatcherDsl : TextWatcher {
private var afterTextChanged: ((s: Editable?) -> Unit)? = null
private var beforeTextChanged: ((s: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? =
null
private var onTextChanged: ((s: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? =
null
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)
}
fun afterTextChanged(after: (s: Editable?) -> Unit) {
afterTextChanged = after
}
fun beforeTextChanged(before: (s: CharSequence?, start: Int, count: Int, after: Int) -> Unit) {
beforeTextChanged = before
}
fun onTextChanged(onChanged: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit) {
onTextChanged = onChanged
}
}
复制代码
这里面涉及到kotlin
的参数方法内容(即:方法能够直接做为参数传递进),不懂自行百度,再也不讲解。code
接下来,来实现一个DSL的扩展方法:orm
inline fun EditText.onTextChange(textWatcher: TextWatcherDsl.() -> Unit): TextWatcher {
val watcher = TextWatcherDsl().apply(textWatcher)
addTextChangedListener(watcher)
return watcher
}
复制代码
ok,搞定了,全部的EditText
都具备了onTextChange
方法,监听文本的方法须要什么写什么。
一、扩展方法再也不具体解释,不是本文重点
二、这里的inline
是指内联方法,即:在编译时期,代码会直接插入掉用处,实际上不是调用外部方法。也就不会形成调用外部方法而致使的性能开销,有兴趣的小伙伴能够百度了学习。
这里须要注意理解下参数TextWatcherDsl.() -> Unit
,TextWatcherDsl
是咱们刚刚自定义的类,而后后面跟了一个点
,就是说,这个参数能够接收TextWatcherDsl
类里的全部方法,只要是它里面的方法均可以传递进来。
咱们再来看下Google官方对于SharedPreferences
的扩展。惯例,咱们Java
中使用SP写入数据是这样的:
SharedPreferences sp = getSharedPreferences("demo", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("key1", "value1");
editor.putString("key2", "value2");
editor.apply();
复制代码
在kotlin
中是这样的:
val sp = getSharedPreferences("demo", Context.MODE_PRIVATE)
sp.edit {
putString("key1", "value1")
putString("key2", "value2")
}
复制代码
是否是简单易读。
咱们来看下官方Google是如何实现的这个方法:
inline fun SharedPreferences.edit( commit: Boolean = false, action: SharedPreferences.Editor.() -> Unit
) {
val editor = edit()
action(editor)
if (commit) {
editor.commit()
} else {
editor.apply()
}
}
复制代码
是的,没错就这么点。
参数SharedPreferences.Editor
后面跟了一个点
,能够接受SharedPreferences.Editor
中的方法,例如putString
上面的写法,会kotlin
的小伙伴应该都见过了。接下来,我来展现下另外一种DSL的写法,可能大家会不多用。
这里我操做File文件的方法来展现。这里我再也不写java代码。
首先咱们看一下常规拷贝文件的写法:
fun copyTo(form:File, to: File) {
// 具体操做文件拷贝的代码
}
复制代码
使用:
copyTo(file1, file2)
复制代码
这种太常见了,Java里也是如此操做的,不细说了。
接下来改造下,写成扩展方法:
fun File.copyTo(to: File) {
// 具体操做文件拷贝的代码
}
复制代码
使用:
file1.copyTo(file2)
复制代码
看起来好像舒服了那么一点
infix fun File.copyTo(to: File) {
// 具体操做文件拷贝的代码
}
复制代码
使用:
file1 copyTo file2
复制代码
注意看扩展方法前面多了一个infix
来修饰方法,是否是很是接近了咱们人类说话时的语言方式。
大家的表情是这样的:
相似的方法,在anko
库中中也有不少地方使用,多去阅读源码就会发现。
本次的简介就到此为此,但愿经过直接的代码展现,能让各位找到些感受