在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("收尾日志已写入")
            }
        }
    }
相关推荐
2401_833269309 小时前
RecyclerView多布局详解
android
v_34836087629 小时前
Android_8 zygote启动分析
android
消失的旧时光-19439 小时前
Android 系统层扫盲 11:JNI 到底是什么?Java / Kotlin 是怎么调用 C/C++ 的?
android·binder·zygote·system_server·aops
mmsx10 小时前
Android 地图几万要素卡成幻灯片?顶点缓冲批上传与显存复用
android·opengl·地图·栅格
北京自在科技20 小时前
谷歌 Find Hub 迎来新版本更新
android·安卓
古法安卓1 天前
Android-休眠唤醒后onLocationChanged没有数据问题排查
android·java·android studio
Htr_1 天前
Creem 2.0 使用指南:面向 AI 构建时代的资金平台
android·数据库·人工智能·ui·photoshop
wardenlzr1 天前
车机看门狗(Watchdog)为何会让整机硬重启
android·优化·车机
IT毕设实战小研1 天前
基于大数据的商场商铺数据分析与可视化的设计与实现
android·java·大数据·django·课程设计