在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("收尾日志已写入")
            }
        }
    }
相关推荐
努力努力再努力wz2 小时前
【MySQL入门系列】掌握表数据的 CRUD:DML 核心语法与执行逻辑解析
android·开发语言·数据结构·数据库·c++·b树·mysql
zh_xuan4 小时前
Android gradle任务
android·gradle构建
Grackers4 小时前
Android Perfetto 系列 10:Binder 调度与锁竞争
android·binder
李白你好5 小时前
Android 自动化渗透测试指令生成
android·自动化
CeshirenTester6 小时前
Claude Code 不只是会写代码:这 10 个 Skills,才是效率分水岭
android·开发语言·kotlin
朝星7 小时前
Android开发[2]:Flow
android·kotlin
zzb15807 小时前
Android Activity 与 Intent 学习笔记
android·笔记·学习
studyForMokey7 小时前
【Android面试】动画 & Bitmap
android·面试·职场和发展
黑牛儿8 小时前
面试高频问题:从浏览器请求到PHP响应:完整流程拆解
android·后端·面试·php
y小花9 小时前
安卓USB服务概述
android·usb