使用单例模式结合工厂构造函数实现Flutter防抖(非Completer)

146 阅读2分钟

整个 Debouncer 类的设计旨在通过延时和取消前一个未完成的延时操作来实现防抖功能,同时使用单例模式结合工厂构造函数和静态缓存来支持不同的防抖时间需求。

以下为使用工厂构造函数来实现带有特定防抖时间的单例模式。

import 'dart:async';
import 'dart:ui';

class Debouncer {
  final int milliseconds;
  //VoidCallback 是一个无参数,无返回值的函数类型。
  VoidCallback? action;
  Timer? _timer;

  // 私有构造函数
  // Debouncer._ 是一个私有的命名构造函数(由于构造函数名前的下划线 `_` 表示它是私有的)。
  // 这意味着这个构造函数只能在 `Debouncer` 类的内部被调用,
  // 从而防止了外部代码直接通过 `new Debouncer._()` 来创建 `Debouncer` 的实例。
  Debouncer._(this.milliseconds);

  // 用于存储不同防抖时间间隔的单例实例
  static final Map<int, Debouncer> _cache = {};

  
  // 定义了一个工厂构造函数 `Debouncer` ,它接受一个可选的整数参数 `milliseconds` ,默认值为500。
  factory Debouncer([int milliseconds = 500]) {
    // 获取单例实例,如果不存在则创建
    if (!_cache.containsKey(milliseconds)) {
      _cache[milliseconds] = Debouncer._(milliseconds);
    }
    return _cache[milliseconds]!;
  }

  // 运行防抖动作
  void run(VoidCallback action) {
    // 如果计时器还在运行,则取消上一次的动作
    if (_timer != null) {
      _timer!.cancel();
    }
    // 重新启动计时器
    // 创建一个新的 `Timer` 实例,它在等待指定的 `milliseconds` 时间后执行 `action` 。
    // 这里用到了 `Duration` 类来指定延时时间, `action` 是延时结束后执行的动作。
    // 这样,只有在指定的时间间隔内没有新的动作请求时, `action` 才会被执行,实现了防抖功能。
    _timer = Timer(Duration(milliseconds: milliseconds), () { 
        action(); 
        // 动作执行完毕后,将_timer置为null 
        _timer = null; 
    });
  }
  
  // 允许用户在需要时显式地取消当前的计时器。
  // 这提供了额外的灵活性,允许 `Debouncer` 在不同情况下更好地控制计时器的行为。
  void cancel() { 
      if (_timer != null) { 
          _timer!.cancel(); 
          _timer = null; 
      } 
  }
}

这样,你就可以根据需要为不同的场景创建具有不同防抖时间的 Debouncer 实例了,例如:

// 创建一个防抖时间为1000毫秒的Debouncer实例
Debouncer customDebouncer = Debouncer(1000); 
customDebouncer.run(() {
  // 执行某些操作
});