防抖(debounce)
是指在触发事件后,在 n 秒内函数只能执行一次。如果在 n 秒内再次触发事件,将重新计算函数执行时间。防抖常用于实时搜索,当用户连续输入时,只有在停止输入后才会触发搜索接口。
// https://www.huizhanii.com
import 'dart:async';
Map<String, Timer> _funcDebounce = {};
/// 函数防抖
/// [func]: 要执行的方法
/// [milliseconds]: 要迟延的毫秒时间
Function debounce(Function func, [int milliseconds = 500]) {
assert(func != null);
Function target = () {
String key = func.hashCode.toString();
Timer _timer = _funcDebounce[key];
if (_timer == null) {
func?.call();
_timer = Timer(Duration(milliseconds: milliseconds), () {
Timer t = _funcDebounce.remove(key);
t?.cancel();
t = null;
});
_funcDebounce[key] = _timer;
}
};
return target;
}
调用:
// https://www.huizhanii.com
void onSearch() {}
debounce(onSearch, 1000)();
节流(throttle)
是让函数有节制地执行,而不是无节制地触发一次就执行一次。节流的含义是在某个时间段内只能执行一次。节流常用于按钮重复提交的场景。
// https://www.huizhanii.com
import 'dart:async';
Map<String, bool> _funcThrottle = {};
/// 函数节流
/// [func]: 要执行的方法
Function throttle(Future Function() func) {
if (func == null) {
return func;
}
Function target = () {
String key = func.hashCode.toString();
bool _enable = _funcThrottle[key] ?? true;
if (_enable) {
_funcThrottle[key] = false;
func().then((_) {
_funcThrottle[key] = false;
}).whenComplete(() {
_funcThrottle.remove(key);
});
}
};
return target;
}
调用:
// https://www.huizhanii.com
Future<void> onSubmit() async {}
throttle(onSubmit)();
封装方法复用参考
// https://www.huizhanii.com
class CommonUtil {
static const deFaultDurationTime = 300;
static Timer timer;
// 防抖函数
static debounce(Function doSomething, {durationTime = deFaultDurationTime}) {
timer?.cancel();
timer = new Timer(Duration(milliseconds: durationTime), () {
doSomething?.call();
timer = null;
});
}
// 节流函数
static const String deFaultThrottleId = 'DeFaultThrottleId';
static Map<String, int> startTimeMap = {deFaultThrottleId: 0};
static throttle(Function doSomething, {String throttleId = deFaultThrottleId, durationTime = deFaultDurationTime, Function continueClick}) {
int currentTime = DateTime.now().millisecondsSinceEpoch;
if (currentTime - (startTimeMap[throttleId] ?? 0) > durationTime) {
doSomething?.call();
startTimeMap[throttleId] = DateTime.now().millisecondsSinceEpoch;
} else {
continueClick?.call();
}
}
}
使用
// https://www.huizhanii.com
GestureDetector(
onTap: () => CommonUtil.throttle(onTap, durationTime: durationTime)
)
CommonUtil.debounce(searchApi)