在Android中,kotlin 的一些开发技巧(二)

之前在 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("收尾日志已写入")
            }
        }
    }
相关推荐
脚踏实地,坚持不懈!5 分钟前
Android ANR 内核底层全解析:从一次触摸到“应用无响应”
android·linux
xhBruce25 分钟前
强制使用桌面模式 - SECONDARY_HOME -android-15.0.0_r23
android·launcher3
_祝你今天愉快11 小时前
从驱动来分析服务的添加过程
android
Dovis(誓平步青云)14 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
alexhilton15 小时前
让架构边界变成可执行的测试
android·kotlin·android jetpack
hai_android16 小时前
SendChannel 与 ReceiveChannel 通信机制
android
数据治理自习室18 小时前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
爱笑鱼19 小时前
Android 系统启动机制(五):system_server 是 init 启动的,还是 Zygote fork 出来的?
android
智购科技无人售货机工厂20 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
开开心心就好20 小时前
电子教鞭工具支持画框写字插图片功能齐全
android·开发语言·前端·javascript·人工智能·pdf·html