Flutter - 实现防抖和节流

news2024/11/28 0:32:42

demo 地址: https://github.com/iotjin/jh_flutter_demo
代码不定时更新,请前往github查看最新代码

什么是防抖和节流?

函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象
是应对频繁触发事件的优化方案。

防抖(debounce)

防抖就是防止抖动,避免事件的重复触发。
防抖可以概括为触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
n 秒后执行该事件,若在n秒后被重复触发,则重新计时
简单的说,如果某一事件被连续快速地触发多次,只会执行最后那一次。

  • 实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
  • 如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟

使用场景

  • input 搜索录入,用户不断录入值
  • window触发resize事件
  • mousemove 鼠标滑动事件
  • scroll滚动条滑动请求、上拉触底加载更多
  • 表单验证,按钮的提交事件

节流(throttle)

节流就是减少流量,将频繁触发的事件减少,并每隔一段时间执行。会控制事件触发的频率。所以节流会稀释函数的执行频率。
n 秒内只运行一次,若在n秒内重复触发,只有一次生效。
如果连续快速地触发多次,在规定的时间内,只触发一次。如限制1s,则1s内只执行一次,无论怎样,都在会1s内执行相应的操作。

  • 实现方式:每次触发事件时,如果当前有等待执行的延时函数,则直接return
  • 如果事件在规定的时间间隔内被不断的触发,则调用方法在规定时间内都会执行一次

使用场景

  • 获取验证码
  • 鼠标不断点击触发,mousedown(规定时间内只触发一次)
  • mousemove 鼠标滑动事件
  • 滚动条滑动请求、上拉触底加载更多
  • 搜索、提交等按钮功能

防抖和节流之间的差别:

相同点:

  • 都可以通过使用 setTimeout 实现
  • 目的都是,降低回调函数的执行频率,节省计算资源

不同点:

  • 防抖,是在一段连续操作结束之后,处理回调,利用 clearTimout 和 setTimeout 实现。

  • 节流,是在一段连续操作中,每一段时间只执行一次,在频率较高的事件中使用来提高性能。

  • 防抖用于无法预知的用户主动行为,如用户输入内容去服务端动态搜索结果。用户打字的速度等是无法预知的,具有非规律性。

  • 节流可用于一些非用户主动行为或者可预知的用户主动行为,如用户滑动商品橱窗时发送埋点请求、滑动固定的高度是已知的逻辑,具有规律性。

  • 防抖是关注于最后一次的事件触发,而节流则是在规定的时间里只执行一次。

  • 防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行

防抖和节流 utils

 class JhCommonUtils {
  static Timer? _debounceTimer;

  /// 防抖 (传入所要防抖的方法/回调与延迟时间)
  static void debounce(Function func, [int delay = 500]) {
    if (_debounceTimer != null) {
      _debounceTimer?.cancel();
    }
    _debounceTimer = Timer(Duration(milliseconds: delay), () {
      func.call();
      _debounceTimer = null;
    });
  }

  /// 防抖 (传入所要防抖的方法/回调与延迟时间)
  static debounce2(Function func, [int delay = 500]) {
    Timer? timer;
    return () {
      if (timer != null) {
        timer?.cancel();
      }
      timer = Timer(Duration(milliseconds: delay), () {
        func.call();
        timer = null;
      });
    };
  }

  /// 录入框防抖 (传入所要防抖的方法/回调与延迟时间)
  static debounceInput(Function(dynamic) func, [int delay = 500]) {
    Timer? timer;
    return (dynamic value) {
      if (timer != null) {
        timer?.cancel();
      }
      timer = Timer(Duration(milliseconds: delay), () {
        func.call(value);
        timer = null;
      });
    };
  }

  static Timer? _throttleTimer;
  static bool _throttleFlag = true;

  /// 节流 (传入所要节流的方法/回调与延迟时间)
  static void throttle(Function func, [int delay = 500]) {
    if (_throttleFlag) {
      func.call();
      _throttleFlag = false;
      return;
    }
    if (_throttleTimer != null) {
      return;
    }
    _throttleTimer = Timer(Duration(milliseconds: delay), () {
      func.call();
      _throttleTimer = null;
    });
  }

  /// 节流 (传入所要节流的方法/回调与延迟时间)
  static throttle2(Function func, [int delay = 500]) {
    Timer? timer;
    bool firstTime = true;
    return () {
      if (firstTime) {
        func.call();
        firstTime = false;
        return;
      }
      if (timer != null) {
        return;
      }
      timer = Timer(Duration(milliseconds: delay), () {
        func.call();
        timer = null;
      });
    };
  }

  /// 节流 (传入所要节流的方法/回调与延迟时间)
  static throttle3(Function func, [int delay = 500]) {
    Timer? timer;
    bool isExecuting = false;
    return () {
      if (isExecuting) return;
      isExecuting = true;
      timer?.cancel();
      timer = Timer(Duration(milliseconds: delay), () {
        func.call();
        isExecuting = false;
      });
    };
  }
}  

未处理时,录入文字改变就会触发一次事件,或者点击一次就会触发一次事件

在这里插入图片描述

防抖处理后
录入文字使用的防抖,设置的1.0秒间隔,一直录入只在最后一次录入结束触发
按钮防抖同样,一直点击只在最后一次点击触发

在这里插入图片描述

节流处理后
点击按钮使用节流,设置的2秒间隔,点击多次2秒内只会触发一次
在这里插入图片描述

用法(关键代码):

一种是在回调函数内部调用工具类,一种是在某个回调函数上使用

 // 防抖 用法一
 _input1() {
    return JhFormInputCell(
      title: '防抖1:',
      text: _keyWord1,
      hintText: '请输入',
      maxLength: 140,
      textInputAction: TextInputAction.search,
      inputCallBack: (value) {
        print('防抖1 未处理1 _keyWord1 : $value');
        JhCommonUtils.debounce(() => _inputCallBack1(value, false), 500);
      },
      inputCompletionCallBack: (value, isSubmitted) {
        print('防抖1 未处理2 _keyWord1 : $value');
        if (isSubmitted) {
          print('防抖1 未处理3 _keyWord1 : $value');
          JhCommonUtils.debounce(() => _inputCallBack1(value, true), 500);
        }
      },
    );
  }
  
 // 防抖 用法二
 _input2() {
    return JhFormInputCell(
      title: '防抖2:',
      text: _keyWord2,
      hintText: '请输入',
      maxLength: 140,
      textInputAction: TextInputAction.search,
      inputCallBack: JhCommonUtils.debounceInput((value) {
        print('防抖后 防抖2 _keyWord2 : $value');
        JhProgressHUD.showText('防抖2 _keyWord2 : $value');
        setState(() {
          _keyWord2 = value;
          // 其他操作
        });
      }, 500),
      inputCompletionCallBack: (value, isSubmitted) {
        print('防抖2 未处理2 _keyWord2 : $value');
        if (isSubmitted) {
          print('防抖2 未处理3 _keyWord2 : $value');
          JhCommonUtils.debounce(() => _inputCallBack2(value, true), 500);
        }
      },
    );
  }

 _inputCallBack1(value, isSubmitted) {
    print('防抖后 防抖1 _keyWord1 : $value');
    JhProgressHUD.showText('防抖1 _keyWord1 : $value');
    setState(() {
      _keyWord1 = value;
      // 其他操作
    });
  }

  _inputCallBack2(value, isSubmitted) {
    print('防抖后 防抖2 _keyWord2 : $value');
    JhProgressHUD.showText('防抖2 _keyWord2 : $value');
    setState(() {
      _keyWord2 = value;
      // 其他操作
    });
  }

  // 节流 用法一
  JhButton(
     text: '按钮-节流1',
     onPressed: () {
       print('点击按钮-节流1');
       JhCommonUtils.throttle(() => _clickThrottleBtn1(), 2000);
     },
   ),
  // 节流 用法二
  JhButton(
    text: '按钮-节流2',
    onPressed: JhCommonUtils.throttle2(() {
      print('节流后 - 点击按钮-节流2');
      JhProgressHUD.showText('点击按钮-节流2,2000ms');
    }, 2000),
  ),
  _clickThrottleBtn1() {
    print('节流后 - 点击按钮-节流1');
    JhProgressHUD.showText('点击按钮-节流1,2000ms');
  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/428761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AgentGPT,免费易用的 Auto-GPT 平替

你问 ChatGPT 答,属于单线问答式交互。但如果你问Auto-GPT,他会分解成N个任务,并且在遇到任务无法完成后,会尝试其它的方式来完成任务,很像老板交待你一个任务,中间的过程他不过问,遇到问题你自…

性能测评:腾讯云轻量服务器4核8G12M带宽流量CPU主频型号

腾讯云轻量4核8G12M应用服务器带宽,12M公网带宽下载速度峰值可达1536KB/秒,折合1.5M/s,每月2000GB月流量,折合每天66GB,系统盘为180GB SSD盘,地域节点可选上海、广州或北京,4核8G服务器网来详细…

【LeetCode】917. 仅仅反转字母、387. 字符串中的第一个唯一字符

作者:小卢 专栏:《Leetcode》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 目录 917. 仅仅反转字母 387. 字符串中的第一个唯一字符 917. 仅仅反转字母 917. 仅仅反转字母…

光栅和矢量图像处理SDK:Graphics Mill 11.7Crack

Graphics Mill 是适用于 .NET 和 ASP.NET 开发人员的最强大的成像工具集。它允许用户轻松地向 .NET 应用程序添加复杂的光栅和矢量图像处理功能。 光栅图形 加载和保存 JPEG、PNG PSD 和其他 8 种图像格式 调整大小、裁剪、自动修复、色度键和 30 多种其他图像处理 使用任何维度…

大电流的走线和过孔

工程师在设计的时候,很容易忽略走线宽度的问题,因为在数字设计时,走线宽度不在 考虑范围里面。通常情况下,都会尝试用最小的线宽去设计走线,这时,在大电流时,将会导致很严重的问题。下面的公式用…

Vue3文字滚动(TextScroll)

可自定义设置以下属性&#xff1a; 滚动文字数组&#xff08;sliderText&#xff09;&#xff0c;类型&#xff1a;Array<{title: string, link?: string}>&#xff0c;必传&#xff0c;默认[] 滚动区域宽度&#xff08;width&#xff09;&#xff0c;类型&#xff1a;…

智能汽车迈进中央计算“芯”时代

全新一代的中央计算E/E架构正在加速到来。《高工智能汽车研究院》认为&#xff0c;伴随着整车电子电气架构从分布式架构、域控制器架构到中央计算架构演变&#xff0c;整个智能汽车供应链体系即将发生重构。 其中&#xff0c;车规芯片是至关重要的一环&#xff0c;从底层支撑着…

海创高科及时充系列共享充电宝 打开共享充电宝行业新局面

---让行业更加透明&#xff0c;更加真诚 在当下&#xff0c;电子产品很普遍。在使用电子产品的时候&#xff0c;需要进行充电。因此&#xff0c;各种充电宝有很大的市场需求。有些创业者感兴趣&#xff0c;那么&#xff0c;充电宝加盟哪个牌子好些&#xff1f;我们推荐海创高科…

【C语言】volatile关键字

文章目录一. 基本介绍二. 演示实验三. const 能否和 volatile 一起使用一. 基本介绍 volatile用来修饰变量&#xff0c;告知编译器不要对这个变量进行优化&#xff0c;每次要用到这个变量时都必须从内存中读取它的值。 看下面一段代码&#xff1a; 在 C/C 中被 const 修饰的…

激活函数(Activation Function)

目录 1 激活函数的概念和作用 1.1 激活函数的概念 1.2 激活函数的作用 1.3 通俗地理解一下激活函数&#xff08;图文结合&#xff09; 1.3.1 无激活函数的神经网络 1.3.2 带激活函数的神经网络 2 神经网络梯度消失与梯度爆炸 2.1 简介梯度消失与梯度爆炸 2.2 梯度不稳…

Java基础——缓冲流

&#xff08;1&#xff09;缓冲流概述&#xff1a; 缓冲流也称高效流&#xff0c;或者高级流。&#xff08;字节流可称原始流&#xff09;作用&#xff1a;缓冲流自带缓冲区&#xff0c;可以提高原始字节流&#xff0c;字符流读写数据的性能。&#xff08;2&#xff09;字节缓…

水质站房式在线监测系统集方案要点

水质在线自动监测系统是一套高度集成的一体化水质自动监测系统&#xff0c;其中包含水样采集处理、水质自动分析、数据采集传输、远程操作监控于一体的在线全自动监控系统。 本次方案整体系统采用一体化集成方式&#xff0c;辅助设备工艺制作精细&#xff0c;同时系统工艺流程…

阿木动态 | 阿木实验室亮相第58·59届中国高等教育展(重庆)

4月10日&#xff0c;第58.59届中国高等教育博览会在重庆国际博览中心圆满结束。本届展会中&#xff0c;各大科技企业、研发机构和教育组织都集中展示了最新的教育科技成果和应用。 阿木实验室作为一家注重提高客户研发效率的企业&#xff0c;此次展会中&#xff0c;阿木实验室 …

MinIO安装配置访问以及SpringBoot整合MinIO

MinIO 1.MinIO安装 Minio 是个基于 Golang 编写的开源对象存储服务&#xff0c;存储非结构化数据&#xff0c;如&#xff1a;图片&#xff0c;视频&#xff0c;音乐等 官网地址&#xff1a;https://min.io/ 中文地址&#xff1a;http://minio.org.cn 官网文档&#xff08; …

行业首选|墨菲安全实力入选《开发安全产品及服务购买决策参考》

十分钟快速部署&#xff0c;为企业提供最高效可靠的软件供应链安全解决方案&#xff01; 近日&#xff0c;GoUpSec 深入调研了14家国内开发安全“酷厂商”&#xff08;包括专业厂商和综合安全厂商&#xff09;&#xff0c;从产品功能、应用行业、成功案例、安全策略等维度对各厂…

DAY 41 WEB和HTTP协议

HTML概述 HTML叫做超文本标记语言&#xff0c;是一种规范&#xff0c;也是一种标准&#xff0c;它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件&#xff0c;通过在文本文件中添加标记符&#xff0c;可以告诉浏览器如何显示其中的内容。 HTML命令可…

Android 纯应用的业务需求越来越窄,可否转向“智能座舱”?

回想2012年—2018年可谓是中国移动互联网的黄金时代&#xff0c;应用市场几乎每天都有新的App应用上线。 而如今却发生了巨大的改变&#xff0c;纯应用的业务需求越来越窄&#xff0c;岗位也随之收缩&#xff0c;这是作为Android开发者不容略的事实。 造成这种现象的原因是互…

类模板的三种表达方式

一:所有的类模板函数写在类的内部 template <typename T> class A { public:A(T a0) {this->a a;}T& getA() {return this->a;}A operator(const A& other) {A temp;//要求A的构造函数要有默认值temp.a this->a other.a;return temp;} private:T a;…

Java语言请求示例,电商商品详情接口,关键词搜索接口,代码封装

Java是一种编程语言&#xff0c;被特意设计用于互联网的分布式环境。Java具有类似于C语言的“形式和感觉”&#xff0c;但它要比C语言更易于使用&#xff0c;而且在编程时彻底采用了一种“以对象为导向”的方式。 使用Java编写的应用程序&#xff0c;既可以在一台单独的电脑上…

红十字救护员急救知识培训笔记

文章目录1、线上学习&#xff1a;理论知识2、线下培训&#xff1a;理论考试3、线下培训&#xff1a;实操学习实操考试3.1 心肺复苏CPR3.2 气道异物梗阻3.3 创伤救护一共有三个步骤 1、线上学习理论课程&#xff0c;所有课程进度100%可以报名线下 2、线下有一个实操的培训&#…