179 lines
4.6 KiB
Markdown
179 lines
4.6 KiB
Markdown
---
|
||
front:
|
||
hard: 进阶
|
||
time: 8分钟
|
||
---
|
||
|
||
|
||
# 节流与防抖函数
|
||
|
||
> 本文部分来自于 [https://github.com/TabooLib/taboolib](https://github.com/TabooLib/taboolib) 源代码注释
|
||
## 节流函数
|
||
### 概念
|
||
节流函数(Throttle Function) 用于限制函数在指定时间间隔内的执行频率,避免函数在短时间内重复触发
|
||
|
||
### 基础节流(无对象绑定)
|
||
创建与特定对象无关的节流操作,在指定时间窗口内仅执行一次操作
|
||
#### 方法签名
|
||
`throttle(delay: Long, action: () -> Unit)`
|
||
#### 示例
|
||
```kotlin
|
||
// 创建一个 500ms 的节流函数
|
||
val throttledAction = throttle(500) {
|
||
println("节流后输出")
|
||
}
|
||
|
||
// 高频使用场景
|
||
throttledAction() // 执行
|
||
throttledAction() // 不会执行
|
||
throttledAction() // 不会执行
|
||
|
||
// 等待 600 毫秒后
|
||
Thread.sleep(600)
|
||
throttledAction() // 重新激活
|
||
|
||
// 最终输出:
|
||
// 节流后输出
|
||
// 节流后输出
|
||
```
|
||
|
||
### 对象绑定节流
|
||
针对特定类型对象(如 Player)的节流操作,不同对象独立计算时间窗口
|
||
#### 方法签名
|
||
`throttle<K : Any>(delay: Long, noinline action: (K) -> Unit)`
|
||
#### 示例
|
||
```kotlin
|
||
val playerThrottle = throttle<Player>(500) { player ->
|
||
println("${player.name} 触发操作")
|
||
}
|
||
|
||
// 高频使用场景
|
||
playerThrottle(player) // 执行
|
||
playerThrottle(player) // 不会执行
|
||
playerThrottle(player) // 不会执行
|
||
|
||
// 等待 600 毫秒后
|
||
Thread.sleep(600)
|
||
playerThrottle(player) // 重新激活
|
||
|
||
// 最终输出:
|
||
// player 触发操作
|
||
// player 触发操作
|
||
```
|
||
|
||
### 带参数节流
|
||
支持传递额外参数的节流实现,保留首次调用参数,忽略后续参数
|
||
|
||
#### 方法签名
|
||
`throttle<K: Any, T>(delay: Long, action: (K, T) -> Unit)`
|
||
|
||
#### 示例
|
||
```kotlin
|
||
val messageThrottle = throttle<Player, String>(500) { player, msg ->
|
||
println("${player.name}: $msg")
|
||
}
|
||
|
||
// 高频使用场景
|
||
messageThrottle(player, "我是坏黑") // 执行
|
||
messageThrottle(player, "我是奶龙") // 不会执行
|
||
messageThrottle(player, "我是Bkm016") // 不会执行
|
||
|
||
// 等待 600 毫秒后
|
||
Thread.sleep(600)
|
||
messageThrottle(player, "我是神秘人") // 重新激活
|
||
|
||
// 最终输出:
|
||
// player: 我是坏黑
|
||
// player: 我是神秘人
|
||
```
|
||
|
||
### 对比
|
||
|
||
| 特性 | 基础 | 对象绑定 | 带参数 |
|
||
| --- |----|--- |--- |
|
||
|对象关联|❌|✅|✅|
|
||
|参数传递|❌|❌|✅|
|
||
|独立时间窗口|全局|按对象|按对象|
|
||
|适用场景|全局状态操作|玩家行为限制|带参数的行为限制|
|
||
|
||
|
||
## 防抖函数
|
||
### 概念
|
||
防抖函数(Debounce Function) 用于延迟函数执行直到特定时间段内没有新触发,适用于处理高频事件中只需响应最后一次操作的场景
|
||
|
||
### 基础防抖
|
||
创建全局防抖操作,在最后一次调用后等待指定延迟执行动作,期间新调用会重置计时器
|
||
|
||
#### 方法签名
|
||
`debounce(delay: Long, async: Boolean, action: () -> Unit)`
|
||
#### 示例
|
||
|
||
```kotlin
|
||
val debouncedAction = debounce(500) {
|
||
println("防抖后输出")
|
||
}
|
||
|
||
// 连续调用
|
||
debouncedAction()
|
||
debouncedAction() // 重置计时
|
||
debouncedAction() // 取消前两次,延迟 500ms 后执行
|
||
|
||
// 等待 600ms
|
||
Thread.sleep(600)
|
||
|
||
// 最终输出:
|
||
// 防抖后输出
|
||
```
|
||
|
||
### 对象绑定防抖
|
||
针对特定对象(如玩家)使用。在指定时间内只执行一次函数,如果在这段时间内再次调用函数,则重新计时
|
||
#### 方法签名
|
||
`debounce<K: Any>(delay: Long, async: Boolean, action: (K) -> Unit)`
|
||
|
||
#### 示例
|
||
```kotlin
|
||
val debouncedAction = debounce<Player>(500) { player ->
|
||
println("玩家 ${player.name} 的防抖后输出")
|
||
}
|
||
|
||
// 连续调用
|
||
debouncedAction(player)
|
||
debouncedAction(player) // 重置计时
|
||
debouncedAction(player) // 取消前两次,延迟 500ms 后执行
|
||
|
||
// 等待 600 毫秒
|
||
Thread.sleep(600)
|
||
|
||
// 最终输出:
|
||
// 玩家 player 的防抖后输出
|
||
```
|
||
|
||
### 带参数防抖
|
||
支持传递额外参数的防抖实现,保留首次调用参数,忽略后续参数
|
||
#### 方法签名
|
||
`debounce<K: Any, T>(delay: Long, async: Boolean, action: (K, T) -> Unit)`
|
||
#### 示例
|
||
```kotlin
|
||
val debouncedAction = debounce<Player, String>(500) { player, message ->
|
||
println("玩家 ${player. name} 的防抖后输出:$message")
|
||
}
|
||
|
||
// 连续调用
|
||
debouncedAction(player, "消息1")
|
||
debouncedAction(player, "消息2") // 重置计时
|
||
debouncedAction(player, "消息3") // 取消前两次,延迟 500ms 后执行
|
||
|
||
// 等待 600 毫秒
|
||
Thread. sleep(600)
|
||
|
||
// 最终输出:
|
||
// 玩家 player 的防抖后输出:消息3
|
||
```
|
||
### 对比
|
||
|
||
| 特性 | 基础 | 对象绑定 | 带参数 |
|
||
|------|----|--- |--- |
|
||
| 对象关联 |❌|✅|✅|
|
||
| 参数传递 |❌|❌|✅|
|
||
| 计时策略 |全局重置|按对象重置|按对象重置|
|