Compose实现点击防抖,给Modifier添加扩展函数(含扩展函数的原理)

扩展函数的核心原理

  1. 语法层面的 "假象"

    从语法上看,扩展函数似乎是直接 "注入" 到了目标类中,调用时也像调用类的成员函数一样(例如 对象.扩展函数())。但实际上,扩展函数并不会修改目标类的结构,也不会被编译成目标类的成员方法。

  2. 静态解析的工具函数

    编译器会将扩展函数处理为静态工具函数。例如,在 Kotlin 中定义:

    kotlin 复制代码
    fun String.lastChar(): Char {
        return this[this.length - 1]
    }

    编译器会将其转换为类似 Java 的静态方法:

    java 复制代码
    public static Char lastChar(String $this) {
        return $this.charAt($this.length() - 1);
    }

    其中,this 关键字在扩展函数中指向调用该函数的对象实例(即目标类的对象),但本质上是函数的第一个参数。

  3. 编译期绑定,无运行时开销

    扩展函数的调用是编译期确定的,而非运行时动态绑定。编译器会根据调用者的静态类型(声明类型)来匹配对应的扩展函数,而不是根据运行时的实际类型。这意味着:

    • 扩展函数不能覆盖类的成员函数(如果同名,优先调用成员函数)。
    • 无法通过多态实现扩展函数的动态调用。

扩展函数的优势

  1. 避免类膨胀 :无需为扩展功能创建子类或工具类(如 StringUtils),保持代码整洁。
  2. 增强可读性 :调用方式与成员函数一致(对象.函数()),符合直觉。
  3. 兼容第三方类:可以为无法修改源代码的类(如 Java 标准库类、第三方库类)添加功能。

局限性

  1. 无法访问私有 / 受保护成员:扩展函数只能访问目标类的公开成员,因为它本质上是外部函数。
  2. 静态绑定的限制:若子类和父类有同名扩展函数,调用结果由变量的声明类型决定,而非实际类型。
  3. 可能引发命名冲突:多个扩展函数同名时,需要通过显式导入或命名空间区分。

典型应用场景

  • 为基础类型(如字符串、集合)添加便捷操作(如字符串判空、集合过滤)。
  • 为第三方库类补充业务相关功能(如为LocalDateTime添加格式化方法)。
  • 在不破坏原有设计的前提下,逐步扩展类的功能。

Compose实现点击防抖

要求:不破坏Modifier的设计原则的情况下,实现防抖功能

kotlin 复制代码
fun Modifier.debounceClick(
    debounceTime: Long = 2000,
    onClick: () -> Unit
) = this.then( // 使用then()方法连接新的修饰符
   Modifier.composed {
        var lastClickTime by remember { mutableStateOf(0L) }

        Modifier.clickable {
            val currentTime = System.currentTimeMillis()
            if (currentTime - lastClickTime > debounceTime) {
                lastClickTime = currentTime

                onClick()
            }
        }
    }
)

then 是Modifier的方法,作用是用来组合Modifier,我们来看他的源码

kotlin 复制代码
infix fun then(other: Modifier): Modifier =
       //合并
    if (other === Modifier) this else CombinedModifier(this, other)

composed 代码块 返回值是Modifier,composed也是将返回值进行合并,composed的源码

kotlin 复制代码
fun Modifier.composed(
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier = this.then(ComposedModifier(inspectorInfo, factory))

Modifier.clickable 是 factory的返回值 factory的返回值和ComposedModifier进行合并, 进行合并的结果,再和debounceClick的对象进行合并,这样就对Modifier进行了扩展。实现了点击防抖。 发现发明Modifier的人真是个天才。。。

相关推荐
阿巴斯甜18 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker18 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952719 小时前
Andorid Google 登录接入文档
android
黄林晴21 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android