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的人真是个天才。。。

相关推荐
xiangpanf3 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx6 小时前
安卓线程相关
android
消失的旧时光-19437 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon8 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon8 小时前
VSYNC 信号完整流程2
android
dalancon8 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013849 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android9 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才10 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶11 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle