# 使用单例模式结合工厂构造函数实现Flutter防抖(非Completer)介绍了如何实现防抖,但非第一次立即执行。
改造上面的 Debouncer 类以便第一次点击后立即执行,我们需要对 run 方法进行一些调整。
这样,第一次调用 run 方法时,会立即执行传入的 action ,而后续的调用则会受到防抖逻辑的控制。下面是修改后的代码:
import 'dart:async';
import 'package:flutter/foundation.dart';
class Debouncer {
final int milliseconds;
FutureOr<void> action;
Timer? _timer;
bool _firstCall = true;
bool _isExecuting = false; // 新增标志,用于跟踪是否有异步操作正在执行
Debouncer._(this.milliseconds);
static final Map<int, Debouncer> _cache = {};
factory Debouncer([int milliseconds = 500]) {
if (!_cache.containsKey(milliseconds)) {
_cache[milliseconds] = Debouncer._(milliseconds);
}
return _cache[milliseconds]!;
}
void run(Function action) async {
if (_firstCall || !_isExecuting) {
_firstCall = false;
_isExecuting = true;
if (_timer != null) {
_timer!.cancel();
}
try {
// 立即执行操作
await action();
} catch (e) {
// 处理或记录异常
if (kDebugMode) {
print('Error executing action: $e');
}
} finally {
_timer = Timer(Duration(milliseconds: milliseconds), () {
_firstCall = true;
_isExecuting = false;
_timer = null;
});
}
}
}
void cancel() {
if (_timer != null) {
_timer!.cancel();
_timer = null;
}
_firstCall = true;
_isExecuting = false; // 如果取消,重置所有标志
}
}
上面的代码实现了一个基于时间防抖的功能,其中包含了一些改进,如立即执行首次调用和处理异步操作。
1. 错误处理
添加 try-catch 块来改进这一点,确保异常被妥善处理。
2. 状态重置逻辑
在当前实现中, _firstCall 和 _isExecuting 标志的重置是基于计时器回调的。
3. 类型安全性和代码清晰度
使用更具体的函数签名,FutureOr<void> Function() ,来提高代码的清晰度和安全性。
通过这些改进,你可以使 Debouncer 类更加健壮、灵活,并且更好地适应不同的使用场景。