Flutter中的节流与防抖
背景async
在一些计算较为复杂、操做较为耗时或者操做为引发页面重绘的场景,若是事件触发的频率毫无限制,除了带来性能上的负担,还会致使糟糕的用户体验。如:根据输入框输入的内容向服务端查询相关文章,用户屡次点击收藏按钮……ide
防抖(debounce)函数
在触发事件时,不当即执行目标操做,而是给出一个延迟的时间,在该时间范围内若是再次触发了事件,则重置延迟时间,直到延迟时间结束才会执行目标操做。性能
示例spa
如设定延迟时间为500ms,code
- 若是在500ms内没有再次触发事件,则执行目标操做
- 若是在500ms内再次触发了事件,则重置延迟时间,从新开始500ms的延迟,直到500ms结束执行目标操做
效果事件
连续点击收藏按钮,中止点击时才会执行”收藏/取消收藏“操做,只会执行一次”收藏/取消收藏“操做get
imageit
示例代码io
// debounce.dart import 'dart:async'; /// 函数防抖 /// /// [func]: 要执行的方法 /// [delay]: 要迟延的时长 Function debounce( Function func, [ Duration delay = const Duration(milliseconds: 2000), ]) { Timer timer; Function target = () { if (timer?.isActive ?? false) { timer?.cancel(); } timer = Timer(delay, () { func?.call(); }); }; return target; }
// debounce_page.dart Text( '$_count', style: Theme.of(context).textTheme.display1, ), Center( child: RaisedButton.icon( icon: Icon(Icons.add), label: Text('防抖'), onPressed: debounce(() { if (!mounted) { return; } setState(() { _count++; }); }), ), ),
节流(throttle)
在触发事件时,当即执行目标操做,同时给出一个延迟的时间,在该时间范围内若是再次触发了事件,该次事件会被忽略,直到超过该时间范围后触发事件才会被处理。
示例
如设定延迟时间为500ms,
- 若是在500ms内再次触发事件,该事件会被忽略
- 若是500ms延迟结束,则事件不会被忽略,触发事件会当即执行目标操做,并再次开启500ms延迟
效果
连续点击收藏按钮,在第一次点击时会当即执行”收藏/取消收藏“操做,在本次操做执行完成前的屡次点击会被忽略,只会执行一次”收藏/取消收藏“操做。
image
示例代码
// throttle.dart import 'dart:async'; /// 函数节流 /// /// [func]: 要执行的方法 Function throttle( Future Function() func, ) { if (func == null) { return func; } bool enable = true; Function target = () { if (enable == true) { enable = false; func().then((_) { enable = true; }); } }; return target; }
// throttle_page.dart Text( '$_count', style: Theme.of(context).textTheme.display1, ), Center( child: RaisedButton.icon( icon: Icon(Icons.add), label: Text('节流,耗时操做2s'), onPressed: throttle(() async { await Future.delayed(Duration(milliseconds: 2000)); if (!mounted) { return; } setState(() { _count++; }); }), ), ), Divider( height: 8, ), Text( '$_count3', style: Theme.of(context).textTheme.display1, ), Center( child: RaisedButton.icon( icon: Icon(Icons.add), label: Text('不节流,耗时操做2s'), onPressed: () async { await Future.delayed(Duration(milliseconds: 2000)); if (!mounted) { return; } setState(() { _count3++; }); }, ), ),
做者:xiaoxiami003 连接:https://www.jianshu.com/p/2b70ef340e82 来源:简书 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。