之前在 Android中,kotlin 的一些开发技巧 中介绍了七种 Kotlin 技巧,经过一年多 kotlin 的使用,这里再介绍新的开发技巧。
中缀表达式
带有 infix 关键字的方法,可以使用中缀表示法调用。中缀表示法是指忽略该调用的点与圆括号。使用中缀表达式可以实现很多效果,如下所示:
kotlin
// 定义支持 可null 的 > 操作
public infix fun Int?.bigger(other: Int?): Boolean {
return when {
this != null && other != null -> this - other > 0
else -> false
}
}
// 如下所示,结果为 false
val result = 5 bigger null
observable 委托
单例对象 kotlin.properties.Delegates 有一个 observable() 便利函数来创建一个 ReadWriteProperty 委托,该委托将对与其关联的变量或属性的任何修改进行拦截。当发生修改时,委托将调用你用 observable() 函数注册的事件处理程序。如下所示:
kotlin
// 每次赋值时,自动cancel上一个旧job
inline fun <reified T : Job?> cannelJob() = Delegates.observable<T?>(initialValue = null) { property, oldValue, newValue ->
oldValue?.cancel()
}
// 示例如下:
private var myJob: Job? by cannelJob()
// 会自动调用 myJob?.cancel()
myJob = scope.launch {
...
}
vetoable 委托
与使用 observable 注册的处理程序不同,其返回类型为Unit,使用 vetoable 注册的处理程序返回布尔结果。返回值为true表示同意接受修改,false 表示拒绝。如果拒绝,修改将被丢弃。示例如下:
kotlin
fun main() {
// 定义一个Person类,使用vetoable委托限制年龄范围
class Person {
var age: Int by Delegates.vetoable(initialValue = 0) { property, oldValue, newValue ->
// 校验逻辑:年龄必须在0-150之间才允许修改
newValue in 0..150
}
}
val person = Person()
// 1. 合法修改:年龄设为20,符合范围
person.age = 20
println("修改后的年龄:${person.age}") // 输出:修改后的年龄:20
// 2. 非法修改:年龄设为200,超出范围,被否决
person.age = 200
println("修改后的年龄:${person.age}") // 输出:修改后的年龄:20(保留旧值)
// 3. 非法修改:年龄设为-5,同样被否决
person.age = -5
println("修改后的年龄:${person.age}") // 输出:修改后的年龄:20(保留旧值)
}
NonCancellable
withContext (NonCancellable) 会让代码 "无视" 协程取消,应仅用于必须执行的收尾操作,代码示例如下:
scss
val job = scope.launch {
try {
// 模拟建立网络连接
socket = Socket("localhost", 8080)
println("网络连接已建立,执行数据传输...")
delay(10000) // 模拟数据传输(可取消)
} finally {
println("进入 finally 块,准备关闭连接...")
// 必须用 NonCancellable,
// 否则 socket.close() 若包含挂起逻辑会被取消
withContext(NonCancellable) {
socket?.close()
println("网络连接已关闭")
// 模拟挂起的收尾操作(如写入日志)
delay(1000)
println("收尾日志已写入")
}
}
}