Flutter 防抖(立即执行)

381 阅读1分钟

# 使用单例模式结合工厂构造函数实现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 类更加健壮、灵活,并且更好地适应不同的使用场景。