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 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。