是什么
本质上是一个 订阅器(subscription),它会订阅某个 Rx
变量。
每个 Worker
都返回一个 Worker
实例,你可以通过 worker.dispose()
来手动取消监听。
作用:是用来监听一个 Rx
变量,然后在满足不同的触发条件时执行回调。
用途:把副作用逻辑(比如日志打印、网络请求、弹窗提示等)从控制器的 build
方法里分离出来。
Worker 的生命周期
- 一般写在
GetxController.onInit()
中(你写的那样)。 - 因为控制器的生命周期结束时,GetX 会自动
dispose
这些 Worker,不需要你手动清理。 - 如果是自己写在 UI 里,就要注意保存
Worker
对象,手动dispose()
,否则可能内存泄漏。
基本语法:
Worker ever<RxType>(
RxInterface<RxType> listener, // 要监听的 Rx 变量
WorkerCallback<RxType> callback, // 触发时执行的回调
)
// callback 会有一个参数:这个参数是 Rx的值,也就是listener的值
(value)={...}
Worker 的类型
ever
ever(_count, (value) {
print("每次变化都执行 -> $value");
});
作用:每次 _count
发生变化时都会触发回调。
特点:只要有变化,就立刻执行。
使用场景:想要对状态的每次变化都做处理,比如写日志、做 UI 更新、同步远端数据等。
once
once(_count, (value) {
debugPrint("once -> $value");
});
- 作用:只会触发一次,当
_count
第一次发生变化时执行,之后就不会再执行了。 - 使用场景:某个事件只需要监听并处理一次,比如用户第一次登录成功后要做初始化工作。
debounce
debounce(_count, (value) {
debugPrint("debounce -> $value");
}, time: Duration(seconds: 2));
- 作用:防抖(debounce)。
- 当
_count
变化时不会立即执行,而是等到 2 秒内不再有变化时才执行。
- 当
- 使用场景:
- 用户在输入搜索框内容时,频繁触发变化,但只想在用户停止输入一段时间后再执行搜索。
- 减少高频触发带来的资源浪费。
interval
interval(_count, (value) {
debugPrint("interval -> $value");
}, time: Duration(seconds: 1));
作用:节流(throttle)。
_count
变化时,最多每 1 秒触发一次回调。
使用场景:
- 处理一些短时间内可能被疯狂触发的事件,比如按钮点击、滚动事件等。
- 可以避免回调函数执行过于频繁,降低性能消耗。
everAll
everAll([_count, _count2], (values) {
print("任意一个变化都执行 -> $values");
});
everAll
的第一个参数是一个 Rx 变量的列表,比如 [_count, _count2]
。
每当 其中任意一个 Rx 变量发生变化,都会触发回调。
回调参数 values
是一个 List,里面包含了你传入的所有 Rx 的当前值,顺序和你传入的列表一致。
防抖与节流
“防抖(debounce)” 和 “节流(throttle / interval)” 是前端、移动端开发里常见的两个概念,它们都是用来 控制高频事件的触发次数,避免因为用户操作太频繁而带来性能浪费。
防抖(Debounce):事件被触发后,会等一段时间;如果这段时间内事件又被触发,就重新计时。只有等用户停止操作,超过设定时间后才执行一次。
- 一句话:“等你不动了再执行”。
- 例子:
- 你在搜索框里输入「flutter」
- 输入 f → 等待中
- 输入 fl → 等待中
- 输入 flu → 等待中
- …(只要一直在输入就不触发)
- 停止输入 2 秒 → 只触发一次 搜索。
- 你在搜索框里输入「flutter」
- 应用场景:
- 搜索框输入:用户边打字边触发输入事件,但只想在用户停止输入 500ms 后再发送请求。
- 表单校验。
节流(throttle / interval):无论事件触发多频繁,都按照一定的时间间隔执行一次。
- 一句话:“定时触发,不管你点多少次”。
- 例子:
- 你疯狂点击按钮 10 次(间隔 < 1 秒)
- interval(1秒) → 1 秒内只会响应 1 次。
- 如果你连续点击 5 秒,就会触发大约 5 次。
- 应用场景:
- 按钮点击:避免用户在 1 秒内疯狂点击按钮导致重复提交。
- 页面滚动:监听滚动事件,但只想每隔 200ms 处理一次,避免卡顿。
案例
class StateWorkersView extends StatelessWidget {
StateWorkersView({super.key});
// 使用 Get.put() 注册控制器
// 使用直接手动创建的方式已经不行了,不会去执行 ever、once、debounce、interval 等方法
// final controller = CountController();
final CountController controller = Get.put(CountController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("GetBuilder")),
body: Center(
child: Column(
children: [
// 显示
GetX<CountController>(
init: controller,
initState: (_) {},
builder: (ctrl) {
return Text('value -> ${ctrl.count}');
},
),
// 按钮
ElevatedButton(
onPressed: () {
controller.add();
},
child: Text('add'),
),
],
),
),
);
}
}
class CountController extends GetxController {
final _count = 0.obs;
set count(value) => _count.value = value;
get count => _count.value;
final _count2 = 20.obs;
set count2(value) => _count2.value = value;
get count2 => _count2.value;
add() {
_count.value++;
_count2.value++;
}
@override
void onInit() {
super.onInit();
debugPrint("------------onInit----------");
// 每次
ever(_count, (value) {
debugPrint("ever -> $value");
});
// 第一次
once(_count, (value) {
debugPrint("once -> $value");
});
// 防抖 2 秒内
debounce(_count, (value) {
debugPrint("debounce -> $value");
}, time: Duration(seconds: 2));
// 定时器 1 秒
interval(_count, (value) {
debugPrint("interval -> $value");
}, time: Duration(seconds: 1));
// 监听多个值
everAll([_count, _count2], (values) {
debugPrint("任意一个变化都执行 -> ${values.toString()}");
});
}
}
下面是打印的日志:
Restarted application in 1,618ms.
[GETX] Instance "CountController" has been created
I/flutter ( 3720): ------------onInit----------
[GETX] Instance "CountController" has been initialized
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
I/flutter ( 3720): ever -> 1
[GETX] Worker [once] called
I/flutter ( 3720): once -> 1
I/flutter ( 3720): 任意一个变化都执行 -> 1
I/flutter ( 3720): 任意一个变化都执行 -> 21
I/flutter ( 3720): interval -> 1
I/flutter ( 3720): debounce -> 1
I/flutter ( 3720): ever -> 2
I/flutter ( 3720): 任意一个变化都执行 -> 2
I/flutter ( 3720): 任意一个变化都执行 -> 22
I/flutter ( 3720): interval -> 2
I/flutter ( 3720): debounce -> 2