在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。

相关推荐
断剑重铸之日40 分钟前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安42 分钟前
Android Library Maven 发布完整流程指南
android
岁月玲珑1 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟5 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡6 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi006 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil8 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你8 小时前
Android View的绘制原理详解
android
移动开发者1号11 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号11 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin