在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("收尾日志已写入")
            }
        }
    }
相关推荐
三少爷的鞋7 小时前
Java 线程自上而下,Kotlin 协程自下而上
android
好的佩奇8 小时前
Dart 之增强枚举
android·flutter·dart
梦影_9 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
好的佩奇11 小时前
蓝牙之无线电与通信距离
android·flutter·蓝牙
vilya11 小时前
我把一套完整的 Python Agent 运行时塞进手机 APK:依赖闭包、Rust 轮子和三个真机坑
android
呆呆敲代码的小Y13 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
思想觉悟15 小时前
SEAndroid实战
android·linux·c++
思想觉悟15 小时前
Aosp开发磨刀石之ADB速查
android·c++
我是唐青枫16 小时前
Kotlin Inheritance(继承)详解:语法、原理、实战 Demo
开发语言·kotlin
应用市场18 小时前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理