在实际的开发当中经常会遇到按钮防止疯狂点击的需求,这也是测试同学要测试的一个用例,所以就针对性的封装了一个类在工作中使用,感觉还不错,特此分享,不喜勿喷.
import 'dart:async';
import 'package:flutter/cupertino.dart';
extension FunctionExt on Function {
VoidCallback throttle() {
return FunctionProxy(this).throttle;
}
VoidCallback throttleWithTimeout({int? timeout}) {
return FunctionProxy(this, timeout: timeout).throttleWithTimeout;
}
VoidCallback debounce({int? timeout}) {
return FunctionProxy(this, timeout: timeout).debounce;
}
}
class FunctionProxy {
static final Map<String, bool> _funcThrottle = {};
static final Map<String, Timer> _funcDebounce = {};
final Function? target;
final int timeout;
FunctionProxy(this.target, {int? timeout}) : timeout = timeout ?? 500;
void throttle() async {
String key = hashCode.toString();
bool enable = _funcThrottle[key] ?? true;
if (enable) {
_funcThrottle[key] = false;
try {
await target?.call();
} catch (e) {
rethrow;
} finally {
_funcThrottle.remove(key);
}
}
}
void throttleWithTimeout() {
String key = hashCode.toString();
bool enable = _funcThrottle[key] ?? true;
if (enable) {
_funcThrottle[key] = false;
Timer(Duration(milliseconds: timeout), () {
_funcThrottle.remove(key);
});
target?.call();
}
}
void debounce() {
String key = hashCode.toString();
Timer? timer = _funcDebounce[key];
timer?.cancel();
timer = Timer(Duration(milliseconds: timeout), () {
Timer? t = _funcDebounce.remove(key);
t?.cancel();
target?.call();
});
_funcDebounce[key] = timer;
}
}
使用方式
InkWell(
onTap: () {
}.throttle(),
child: Text(
'风险评估未通过原因',
style: TextStyle(fontSize: 15.sp, color: Colors.white),
),
);