pd_cooldown:别急,给操作一点「冷静期」
一句话简介:这是一个专业的 Flutter 防抖(Debounce)与节流(Throttle)插件,用一个“冷却器”为你的按钮和接口降温,杜绝“手抖连击”和“猛戳服务器”。
- 插件主页:pub.dev/packages/pd…
- 适用场景:表单提交防重复、搜索框输入防抖、按钮点击节流、接口保护与资源限流。
为什么需要「冷却期」?
- 用户手速过快,后端心率过高:多次请求可能导致重复下单、重复扣费、资源占用暴增。
- UI“瞬间爽”,业务“后劲大”:连击交互体验好,但代价是排队、回滚与脏数据。
- 你需要一个“靠谱的保镖”,在窗口时间里只让一次操作通过。
pd_cooldown 的核心就是:在指定的冷却窗口内,第一次触发执行;其后触发被优雅拒绝或延迟,直到时间窗结束。
安装与引入
- 在
pubspec.yaml中添加依赖:
dependencies:
pd_cooldown: ^0.2.1
- 安装依赖:
flutter pub get
- 引入库:
import 'package:pd_cooldown/pd_cooldown.dart';
开箱即用:统一“冷却执行器”
用一个对象守住你的操作,重复触发也不慌。
// 创建防抖/节流统一执行器(默认带日志和错误处理)
final cooldown = PDCooldown.withDefaults(
cooldownDuration: const Duration(seconds: 3),
);
// 在冷却窗口内,仅第一次执行;其后触发会被优雅拒绝(返回 null)
final result = await cooldown.execute<String>(() async {
// 你的异步操作(例如网络请求)
await Future.delayed(const Duration(milliseconds: 500));
return '操作完成';
}, onCooldown: (remaining) {
// 告知用户还需等待多久(可接入 Toast/Tip)
print('冷却中,剩余时间: ${remaining.inSeconds}秒');
});
if (result != null) {
print('执行结果: $result');
} else {
print('操作被冷却限制');
}
常用方法
execute<T>():执行带冷却保护的操作。isInCooldown():是否处于冷却中。getRemainingCooldown():获取剩余冷却时间。reset():重置冷却(如用户取消、需重新尝试时)。
可定制构造
final cooldown = PDCooldown.withCallbacks(
cooldownDuration: const Duration(seconds: 5),
onDebug: (message) => print('调试: $message'),
onError: (message) => print('错误: $message'),
onErrorHandler: (error, stackTrace, prefix) {
// 自定义错误处理逻辑(可接入日志/埋点)
print('$prefix: $error');
},
);
不写业务也能用:内置 UI 组件
直接把按钮换成“带冷却”的版本,连击自然没戏。
节流按钮 PDThrottleButton
- 语义:第一次点击立刻响应,冷却期间忽略后续点击。
PDThrottleButton(
buttonType: PDButtonType.elevated,
debounceDuration: const Duration(seconds: 2),
onPressed: () {
print('节流按钮被点击');
},
child: const Text('节流按钮'),
)
防抖按钮 PDDebounceButton
- 语义:延迟响应,只有在指定时间内没有新点击时才触发。
PDDebounceButton(
buttonType: PDButtonType.elevated,
debounceDuration: const Duration(milliseconds: 800),
onPressed: () {
print('防抖按钮被点击');
},
child: const Text('防抖按钮'),
)
常用属性
onPressed:点击回调。child:子组件。debounceDuration:时间窗口(名称统一,节流/防抖皆用)。buttonType:按钮类型。cooldownOpacity/debounceOpacity:冷却或防抖期间透明度(视觉弱化,提示“还在冷却”)。
常见场景与配方
- 表单提交:节流 3–5 秒,禁止重复下单/扣费;按钮半透明+提示文案。
- 搜索框输入:防抖 300–800 ms,只有“停下来的那次”才请求后端。
- 点赞/收藏:节流 1–2 秒,避免“激情连点”。
- 刷新列表/切换页签:节流 1 秒,避免重复构建与闪烁。
- 上传/支付等高风险操作:节流 5–10 秒,搭配可视冷却反馈。
最佳实践(把冷却用得更优雅)
- 语义分工:
- “节流”:立刻执行一次,其后忽略;适合点击型动作。
- “防抖”:等待稳定后执行;适合输入与搜索。
- 时间窗选择:
- 交互操作:200–800 ms 防抖。
- 网络提交:2–5 s 节流。
- 高风险动作:5–10 s 节流并可视提示。
- 统一封装:将业务常见冷却封装成服务(如
SubmitCooldownService),团队统一调用,避免重复造轮子。 - 可观测性:打通
onDebug/onError到日志系统(Sentry/自研 Logger),便于观察“热手”用户与异常触发。 - UI 反馈:冷却期按钮半透明或禁用;搭配 Loading/Tip 提示“我在工作”。
进阶技巧(让冷却更聪明)
- 多实例分域:搜索与提交各用独立
PDCooldown,互不干扰,避免“误共享”。 - 非阻塞语义:
execute<T>返回null即表示被冷却拒绝;根据此分支设计 UX(如弹出“稍等片刻”)。 - 灵活重置:用户主动取消或失败重试时
reset();严谨控制生命周期,避免“冷却幽灵”。 - 状态管理协作:在
Provider/Bloc/Riverpod中持有PDCooldown对象,清晰管理释放与复用。
常见问答(FAQ)
- Q:透明度降低,用户会以为按钮坏了?
- A:这正是提示“冷却中”的信号。可搭配文字或动画提升感知。
- Q:这和普通
debounce/throttle库有什么不同?- A:
pd_cooldown提供统一执行器与现成按钮组件,API 简洁、语义明确,并支持调试与错误回调,拿来即用。
- A:
- Q:能否并发多次执行?
- A:设计语义是“窗口内只执行一次”,其余拒绝;同步锁保证线程安全,不建议并发破坏语义。
- Q:如何给后端“休息权”?
- A:对可能导致重复下单/扣费的操作,节流 3–5 秒并加不可重复提示,保护服务与用户体验。
- Q:我就想疯狂点,咋办?
- A:我们支持冷静;你的后端更支持午睡。请理性连击。
小结与彩蛋
- 一句话:把“手速竞赛”变成“优雅绅士”,交互顺滑,服务稳健。
- 彩蛋:给“提交按钮”配上节流 + 半透明 + 提示文案——你的后端同事会请你喝奶茶。
参考资料
- pd_cooldown | Flutter package(官方文档与示例):pub.dev/packages/pd…