在Jetpack Compose中优雅的使用防抖、节流

写在前面

本文中提及的use开头的函数,都出自与我的 ComposeHooks 项目,它提供了一系列 React Hooks 风格的状态封装函数,可以帮你更好的使用 Compose,无需关系复杂的状态管理,专心于业务与UI组件。

这是系列文章的第8篇,前文:

防抖、节流的概念不必细说,使用 ComposeHooks 可以帮助我们在Compose中轻松的使用防抖节流!

状态值进行防抖、节流

例如我们的状态来源是一个输入框,我们要对输入框的输入内容进行模糊匹配,这种场景就需要进行节流操作:

kotlin 复制代码
val (state, setState) = useState("")
val throttledState = useThrottle(value = state)

TextField(
    value = state,
    onValueChange = setState,
)

我们使用 useStateTextField 组件创建状态,然后将状态值传入 useThrottle 即可;

现在我们直接使用 throttledState 传递给服务端即可;

与之前介绍的 useRequest 钩子一样,你可以通过 optionsOf 设置节流钩子的相应配置,默认配置如下:

kotlin 复制代码
data class ThrottleOptions internal constructor(
    var wait: Duration = 1.seconds, // 节流时长
    var leading: Boolean = true, // 是否在延迟开始前调用函数
    var trailing: Boolean = true, // 是否在延迟开始后调用函数
)

防抖操作与之类似,自己是效果不同而已:

kotlin 复制代码
val (state, setState) = useState("")
val debouncedState = useDebounce(value = state)

TextField(
    value = state,
    onValueChange = setState,
)

防抖的默认值为:

kotlin 复制代码
data class DebounceOptions internal constructor(
    var wait: Duration = 1.seconds, // 防抖间隔
    var leading: Boolean = false, // 是否在延迟开始前调用函数
    var trailing: Boolean = true, // 是否在延迟开始后调用函数
    var maxWait: Duration = 0.seconds, // 最大等待时长,防抖超过该时长则不再拦截,默认为0(永远防抖)
) 

对函数进行防抖、节流

除了状态值的防抖节流,ComposeHooks 同样支持对函数进行防抖节流:

kotlin 复制代码
val (state, setState) = useState(0)
val throttledFn = useThrottleFn(fn = { setState(state + 1) })

Text(text = "current: $stateFn")
TButton(text = "throttled +1") {
    /** Manual import:`import xyz.junerver.compose.hooks.invoke` */
    throttledFn()
}

我们可以给 useThrottleFn 传递一个函数闭包,这里是一个简单的计数器累加的函数,它的返回值是节流 版的的函数,我们只需要将按钮的点击事件替换为这个throttledFn函数即可实现对原函数的节流操作!非常简单

tips: 同样的我们可以对函数进行防抖,代码几乎一样,我就不赘述了!

进阶用法

在上面的例子中,我们的原函数的签名是()->UnituseThrottleFnfn参数闭包同样支持外部参数的传入,还用上面的例子:

kotlin 复制代码
val (stateFn, setStateFn) = useState(0)
val throttledFn = useThrottleFn(fn = { params -> setStateFn((params[0] as? Int ?: 0) + 1) })

Text(text = "current: $stateFn")
TButton(text = "throttled +1") {
    /** Manual import:`import xyz.junerver.compose.hooks.invoke` */
    throttledFn(Random.nextInt())
}

现在节流函数可以从外部接受参数,在一些场景下他很有必要,需要注意的是params的类型是Array<Any?>,你需要在闭包中对参数进行处理、转型

对副作用进行防抖、节流

与直接使用副作用区别不大,只是对副作用闭包进行了防抖节流:

kotlin 复制代码
val (stateEf, setStateEf) = useState(0)
val (result, setResult) = useState("")
useThrottleEffect(stateEf) {
    setResult("loading")
    // 与 effect相同,这里可以执行协程挂起函数
    val result = NetApi.SERVICE.userInfo("junerver")
    setResult(result.toString().subStringIf())
}

Text(text = "deps: $stateEf")
TButton(text = "+1 trigger effect execute") {
    setStateEf(stateEf + 1)
}
Text(text = result)

这里的计数 stateEf 模拟一个快速变化的值,他会触发 effect 副作用闭包的执行,如果我们直接使用 useEffect 或者官方的的 LaunchedEffect 这个副作用闭包也会不停的执行。

但是使用 useThrottleEffect,他会节流执行副作用,与上面两个钩子一样,他的也可通过 optionsOf 配置具体的节流参数。

tips: 同样的我们可以对副作用进行防抖,代码几乎一样,我就不赘述了!

探索更多

项目开源地址:junerver/ComposeHooks

MavenCentral:hooks

kotlin 复制代码
implementation("xyz.junerver.compose:hooks:1.0.11")

欢迎使用、勘误、pr、star。

相关推荐
法欧特斯卡雷特28 分钟前
Kotlin 2.4.20 现已发布,新特性多不多?
android·开源·全栈
摇滚侠34 分钟前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 31
android·spring boot·笔记
Zeaon1 小时前
别再手写筛选栏了:一个可组合的 Flutter 选择组件(5 入口 × 7 委托)
android·flutter
Michaelwubo1 小时前
mysql8 主从 HA切换
android·adb
墨狂之逸才2 小时前
Android 工业手持机蓝牙扫描失败:为什么同时需要蓝牙和定位权限
android
Android打工仔2 小时前
Kotlin 协程源码解析(七)`delay()` 到底是如何在 `Dispatchers.Main` 上恢复的?
android·kotlin
律宏阔3 小时前
Android 红外功能实现与红外协议开发笔记:ConsumerIrManager、NEC、PWM、曼彻斯特编码
android
mmsx3 小时前
MapLibre 统一图层模型:sealed class + 声明式图层 + XML 持久化
android·源码·地图·maplibre
YUJIANYUE4 小时前
查立得万用查分安卓版(web环境+查询系统免安装单文件一键运行包)
android·前端
天空之城--4 小时前
Android Launcher 性能优化完全指南:从启动到滑动,构建极致流畅的桌面体验
android·性能优化