App使用中避免不了被某些用户疯狂点击一些按钮,造成页面多次跳转或者接口频繁调用,这样很可能对程序造成一些bug,今天我们来处理一下在Flutter中如何防止重复快速点
我们以TextButton为例,对TextButton进行封装处理。
思路:记录第一点击时间,再次点击后判断与第一次的时间差,如果大于我们定义的防抖时间那么就执行点击,否则拦截此次点击。
- 封装 DebounceButton
class DebounceButton extends StatelessWidget {
final VoidCallback? onPressed;
final Widget? child;
final int milliseconds;
final VoidCallback? onLongPress;
final ValueChanged<bool>? onHover;
final ValueChanged<bool>? onFocusChange;
final ButtonStyle? style;
final FocusNode? focusNode;
final bool autofocus;
final Clip clipBehavior;
final MaterialStatesController? statesController;
DebounceButton(
{Key? key,
required this.onPressed,
required this.child,
this.milliseconds = 800,
this.onLongPress,
this.onHover,
this.onFocusChange,
this.style,
this.focusNode,
this.autofocus = false,
this.clipBehavior = Clip.none,
this.statesController})
: super(key: key);
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: onPressed == null
? null
: onPress(fun: onPressed, milliseconds: milliseconds),
onLongPress: onLongPress,
onHover: onHover,
onFocusChange: onFocusChange,
style: style,
focusNode: focusNode,
autofocus: autofocus,
clipBehavior: clipBehavior,
statesController: statesController,
child: child!,
);
}
final TimeData timeData = TimeData();
bool doubleClick(int milliseconds) {
DateTime? lastPressedAt = timeData.lastPressedAt;
if (lastPressedAt == null ||
DateTime.now().difference(lastPressedAt) > Duration(milliseconds: milliseconds)) {
timeData.lastPressedAt = DateTime.now();
return false;
}
return true;
}
Function() onPress({Function()? fun, int milliseconds = 800}) {
return () {
if (doubleClick(milliseconds)) {
return;
}
fun?.call();
};
}
}
class TimeData{
DateTime? lastPressedAt;
}
上面其实就是一个 TextButton 。看似有不少的参数,其实只有 milliseconds 参数是我们自定义的一个防抖时间,其他参数都是TextButton 原有参数。
- 使用就比较简单了,和 TextButton 使用是一致的。
DebounceButton(
onPressed: () {
Printer.error('防抖点击: ${debounceCount++}');
},
child: const Text(
'防抖',
style: TextStyle(color: Colors.white),
),
),
好了,经过前面的一顿操作之后就可以防止重复快速点击!!!
不足之处,欢迎大家指正。