Flutter入门与实战(七十九):稳住了,别抖!—— 看GetX 的Worker如何防抖
前言
在前后端对接过程中,经常会遇到快速重复点击导致重复请求的问题,如果处理不好一方面容易产生垃圾数据,另一方面还增加了很多无谓请求,导致服务器请求数量过多。在 GetX中,针对这种场景提供了一个Worker类以及几个勾子函数来解决这类问题。
场景1:疯狂点击
举个例子,某些购物 App 会提供互动游戏,通过在限定时间内点击的次数来刷红包或优惠券(都是套路😎),这个时候我们会疯狂地点击天上掉下来的红包或者锦鲤,试想如果每次点击都请求后端,那如果是上万人都这么点击,服务器都会被点崩!对于这种情况,GetX
提供了一个 debounce
的勾子函数,这个函数在限定的时间内只会执行一次指定的回调动作:
Worker debounce<T>(
RxInterface<T> listener,
WorkerCallback<T> callback, {
Duration? time,
Function? onError,
void Function()? onDone,
bool? cancelOnError,
});
其中 listener
为状态变量,callback
为状态变量 listener
改变时的回调方法,time
为限定时间。三个参数构成的结果是在小于time
的时间内,如果listener
持续在变化的话就不会执行 callback
。如果在超过time
时间长度内没有变更才会调用一次callback
。举个例子,我们一个计数器counter
,按如下方式设定:
debounce(_counter, (latestValue) => print("callback: $latestValue"), time: Duration(seconds: 1));
然后有一个按钮每点击一次就给计数器的值加1。如果手速够快,我们1秒钟可以点击很多次。这个时候假设我们要防抖,就可以将网络请求放到 callback
里,从而在限定的时间范围内,避免用于的疯狂点击造成过多网络请求,造成类似 DDos 的攻击效果。我们来看一下效果,见下图。
可以看到,我们疯狂点击的时候,回调函数并没有执行,而是停下来间隔一定时间(1秒)才执行。通过这种方式可以减少无谓的请求。这种场景还可以用于搜索场合,当在输入的时候,因为内容在变化,我们不用请求后端数据,而等到用户输入结束之后再请求,这样体验更好而且也能减少后端请求。
场景2:刷金币
在有些场合,我们需要限定一定时间内的请求次数,做类似限流的效果。比如,在点击按钮刷金币的行为,我们可以限制没2秒最多刷1次,这样1分钟内最多只能刷30次,在 GetX
中提供了一个 interval
的方法:
Worker interval<T>(
RxInterface<T> listener,
WorkerCallback<T> callback, {
Duration time = const Duration(seconds: 1),
dynamic condition = true,
Function? onError,
void Function()? onDone,
bool? cancelOnError,
})
使用和 debounce
类似,只是会忽略间隔 time
时间范围内的变化,在状态变量发生变化且每隔 time时间才会调用1次 callback
。同时增加了一个 condition
(一个返回true
或 false
的函数),只有在该函数返回 true
时才会执行 callback
(比如必须是 vip
才可以刷金币)。我们以计数器为例看看效果。
class WorkerController extends GetxController {
final _counter = 0.obs;
set counter(value) => this._counter.value = value;
get counter => this._counter.value;
late Worker worker;
int coinCount = 0;
@override
void onInit() {
worker = interval(
_counter,
(_) {
coinCount++;
print("金币数: $coinCount");
},
time: Duration(seconds: 2),
condition: () => coinCount < 10,
);
super.onInit();
}
@override
void dispose() {
worker.dispose();
super.dispose();
}
}
可以看到金币数每隔1秒才会增加1,而且超过10之后就不再增加了。
其他Worker 勾子函数
GetX 还提供了下面三种 Worker
勾子函数,函数的调用和 interval 一样。
once
:状态变量变化时只执行一次,比如详情页面的刷新只更新一次浏览次数。ever
:每次变化都执行,可以用于点赞这种场合everAll
:用于列表类型状态变量,只要列表元素改变就会执行回调。
Worker 使用注意事项
为避免Worker
反复被注册,应当在 GetxController
的构造方法或 onInit
声明周期注册,或者在 StatefulWidget
的 initState
中注册(不推荐)。注意的是,需要在 dispose
方法中调用Worker
的dispose
方法销毁 Worker
对象。
总结
本篇介绍了 GetX
的 Worker
类以及对应的勾子函数的使用,通过注册 Worker
可以用于应用的防抖和限流,从而防止误触发和降低服务器请求数以降低资源消耗。
转载自:https://juejin.cn/post/7011283880116224007