run
例如现在有这么一个场景,用户领取app的奖励,如果用户没有登录弹出登录dialog,如果已经登录则弹出领取奖励的dialog。我们可以使用以下代码来处理这个逻辑。
run {
if (islogin) loginDialog else getAwardDialog
}.show()
with
对于下面这段代码做的是同样一件事。它们的不同之处就是一个使用了with(T)函数,而另一个则是使用了T.run函数。
with(webView.settings){
javaScriptEnabled = true
databaseEnabled = true
}
webView.settings.run {
javaScriptEnabled = true
databaseEnabled = true
}
但是我们觉得使用哪一个会更好呢?现在假设一种场景,那就是webView.settings可能为null。那我们就来再次看一下下面这段代码.
with(webView.settings){
javaScriptEnabled = true
databaseEnabled = true
}
webView.settings?.run {
javaScriptEnabled = true
databaseEnabled = true
}
这么以来就很明显了,当然是T.run方法会更好,因为我们可以在使用这些函数之前可以进行对null的检查。
对于with也是存在一个返回值,它也是会返回在这个作用域当中的最后一个对象。
作用域中接收者this和it
在这几个扩展函数当中,它们都能直接获取到调用的对象或者是with中传入参数的对象。在这五个扩展函数在它们的作用域中的接收者可以是this或者是it。那么我们来对比一下T.run和T.let函数。这两个函数也是十分的相似。
stringVariable?.run {
println("字符串的长度为$length")
}
stringVariable?.let {
println("字符串的长度为 ${it.length}")
}
在这两段代码中可以清晰的看到。在T.run函数中通过this来获取stringVariable对象,而在T.let函数中通过it来取出stringVariable对象。当然我们也能够为it重新命名。如果我们不想覆盖外部作用域的this,这时候去使用T.let会更加的方便。
在作用域中返回值的类型
在这些作用域中它们都会存在一个返回值。在上面的讲述的run,with,T.run,T.let中它们返回的都是作用域中最后一个对象。当然它们所返回的值是允许和接受者it或者this对象的类型不同。但是并不是所有的扩展函数都是返回作用域的最后一个对象。例如T.also函数。
T.let返回的是作用域中的最后一个对象,它的值和类型都可以改变。但是T.also不管调用多少次返回的都是原来的original对象。
/原始函数
fun makeDir(path: String): File {
val result = File(path)
result.mkdirs()
return result
}
//通过let和also的链式调用改进后的函数
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }
apply
对于T.apply它作用域中的接收者是this,并且返回的调用者T。因此,T.apply的其中一个使用场景可以用来创建一个Fragment,代码如下所示:
// 使用普通的方法创建一个Fragment
fun createInstance(args: Bundle) : MyFragment {
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
// 通过apply来改善原有的方法创建一个Fragment
fun createInstance(args: Bundle)
= MyFragment().apply { arguments = args }
我们也能够通过T.apply的链式调用创建一个Intent:
// 普通创建Intent方法
fun createIntent(intentData: String, intentAction: String): Intent {
val intent = Intent()
intent.action = intentAction
intent.data=Uri.parse(intentData)
return intent
}
// 通过apply函数的链式调用创建Intent
fun createIntent(intentData: String, intentAction: String) =
Intent().apply { action = intentAction }
.apply { data = Uri.parse(intentData) }
扩展函数的特性
- 它们都有自己的作用域
- 它们作用域中的接收者是this或者it
- 它们都有一个返回值,返回最后一个对象(this)或者调用者自身(itself)