Flutter防抖思路

462 阅读1分钟

关于Flutter防止连续点击问题,看其他文章都是延迟触发操作的思路,这样多少会感觉有点卡,如果一直点击的话,就会一直不响应事件。

两种方式, 第一种是不区分事件,统一控制事件的响应间隔

///使用
LwDeBouncer.run((){
  print("lw----触发任务==}${DateTime.now()}");
},customInterval: 500);

第二种是区分事件,只有相同的事件才会控制响应间隔,不同事件之间互不影响。

///使用
LwDeBouncer.call(() {
    print("lw----触发任务index:$index");
  },
  tag: index.toString(),
);
import 'dart:async';

/// 防止连续点击
class LwDeBouncer {
  static Timer? _timer;

  /// 上次执行时间
  static int lastMilliseconds = 0;

  /// 事件间隔
  static int actionInterval = 1000;
  static List<String> actionIds = [];
  static int emptyIndex = 0;

  /// 不区分点击事件,统一事件响应间隔时间
  static run(Function action, {int customInterval = 0}) {
    if (DateTime.now().millisecondsSinceEpoch - lastMilliseconds <
        (customInterval == 0 ? actionInterval : customInterval)) return;
    action();
    lastMilliseconds = DateTime.now().millisecondsSinceEpoch;
  }

  /// 区分事件,只有相同的事件,才会控制间隔时间
  /// tag:外部调用相同函数,触发的不同事件,(例如:ListView的item事件,可以通过添加tag进行区分,)
  static call(Function action, {String? tag}) {
    String actionId = getFunctionIdentify() + (tag != null ? '_$tag' : '');
    if (actionIds.contains(actionId)) return;
    actionIds.add(actionId);
    action();
    startTimer();
  }

  static startTimer() {
    emptyIndex = 0;
    _timer ??= Timer.periodic(Duration(milliseconds: actionInterval), (t) {
      if (actionIds.isNotEmpty) {
        String tem = actionIds.removeAt(0);
      } else {
        if (emptyIndex != 0) emptyIndex = t.tick;
      }

      if (actionIds.isEmpty && emptyIndex < t.tick) {
        _timer?.cancel();
        _timer = null;
      }
    });
  }

  static getFunctionIdentify() {
    String identify = DateTime.now().millisecondsSinceEpoch.toString();
    StackTrace stackTrace = StackTrace.current;
    List<String> frames = stackTrace.toString().split('\n');
    if (frames.length < 3) return identify;
    String funcLine = frames[2];
    if (funcLine.contains('(') && funcLine.contains(')')) {
      funcLine = funcLine.substring(funcLine.indexOf('(') + 1, funcLine.indexOf(')'));
    }
    return funcLine;
  }
}

如果有什么问题,望相互交流