dart防抖和节流


dart 防抖和节流

前端的开发者都或多或少的遇到过节流与防抖的问题。函数节流和函数防抖,两者都是优化执行代码效率的一种手段。在一定时间内,代码执行的次数不一定是越多越好。相反,频繁的触发或者执行代码,会造成大量的重绘等问题,影响浏览器或者机器资源。因此把代码的执行次数控制在合理的范围。既能节省浏览器 CPU 资源,又能让页面浏览更加顺畅,不会因为 js 的执行而发生卡顿。这就是函数节流和函数防抖要做的事。

flutter 也同样有此场景。

防抖(debounce)

防抖在生活中随处可见,毕竟经典的就是电梯,当没人进出电梯的时候,过一段时间它就会自动关上,而如果在它关上之前有人按了开门或者进出电梯,那么电梯关门时间又会重新计时。

在代码里,触发事件时,不立即执行目标操作,而是给出一个延迟的时间,在该时间范围内如果再次触发了事件,则重置延迟时间,直到延迟时间结束才会执行目标操作。

示例

如设定延迟时间为 500ms,

如果在 500ms 内没有再次触发事件,则执行目标操作
如果在 500ms 内再次触发了事件,则重置延迟时间,重新开始 500ms 的延迟,直到 500ms 结束执行目标操作

效果

连续点击防抖按钮,停止点击时才会执行”debounceCount++”操作,只会执行一次操作

示例图

代码

TextButton.icon(
    icon: Icon(Icons.add),
    label: Text('防抖:$debounceCount'),
    onPressed: debounce(() {
      if (!mounted) {
        return;
      }
      setState(() {
        debounceCount++;
      });
    }),
);
/// 函数防抖
///
/// [func]: 要执行的方法
/// [delay]: 要迟延的时长
void Function() debounce(
  Function func, [
  Duration delay = const Duration(milliseconds: 500),
]) {
  Timer? timer;
  void Function() target = () {
    timer?.cancel();
    timer = Timer(delay, () {
      func.call();
    });
  };
  return target;
}
/// 也可以采用类的方式
class Debouncer {
  final Duration? delay;
  Timer? _timer;

  Debouncer({this.delay});

  void call(void Function() action) {
    _timer?.cancel();
    _timer = Timer(delay ?? const Duration(milliseconds: 1000), action);
  }
}

节流(throttle)

在触发事件时,立即执行目标操作,同时给出一个延迟的时间【也有说是先给出延迟时间再执行的】,在该时间范围内如果再次触发了事件,该次事件会被忽略,直到超过该时间范围后触发事件才会被处理。

示例

如设定延迟时间为 500ms,

如果在 500ms 内再次触发事件,该事件会被忽略
如果 500ms 延迟结束,则事件不会被忽略,触发事件会立即执行目标操作,并再次开启 500ms 延迟

效果

连续点击防抖按钮,在本次操作执行完成前的多次点击会被忽略,只会执行一次”throttleCount++”操作。

TextButton.icon(
    icon: Icon(Icons.add),
    label: Text('节流:$throttleCount'),
    onPressed: throttle(() {
      if (!mounted) {
        return;
      }
      setState(() {
        throttleCount++;
      });
    }) as void Function()?,
);
/// 节流
///
/// [func]: 要执行的方法
/// [delay]: 要迟延的时长
Function throttle(
  Function func, [
  Duration delay = const Duration(milliseconds: 500),
]) {
  Timer? timer;
  return () {
    if (timer != null) return;
    timer = Timer(delay, () {
      func.call();
    });
  };
}
class Throttle {
  final Duration delay;
  Timer? timer;

  Throttle({this.delay = const Duration(milliseconds: 500)});

  void call(Function callBack) {
    if (timer != null) return;
    timer = Timer(delay, () {
      callBack.call();
    });
  }
}

文章作者: 小林
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小林 !
评论
  目录