flutter —— 使用 getx 进行状态管理
简单状态管理器
GetxController
有一个 update 方法,用于触发更新操作。
类似于 ChangeNotifier 中的 notifyListeners 方法
源码
abstract class GetxController extends DisposableInterface
with ListenableMixin, ListNotifierMixin {
void update([List
GetBuilder
初始化的时候,会向 Controller 添加回调函数(订阅),这个回调函数的作用就是 setState 更新当前 GetBuilder 组件。
部分源码
class GetBuilderStateextends State > with GetStateUpdaterMixin { T? controller; @override void initState() { super.initState(); controller = widget.init; _subscribeToController(); } // 向 controller 添加当前 GetBuilder 的一个回调 void _subscribeToController() { _remove?.call(); _remove = (widget.id == null) ? controller?.addListener( _filter != null ? _filterUpdate : getUpdate, ) : controller?.addListenerId( widget.id, _filter != null ? _filterUpdate : getUpdate, ); } ... } mixin GetStateUpdaterMixin on State { void getUpdate() { if (mounted) setState(() {}); } }
添加订阅的方法是在 GetxController 中,即向绑定的 controller 的 _updaters 列表中添加当前 GetBuilder 的回调,以便 controller 执行 update() 方法时,通过此回调更新当前 GetBuilder
相关源码
@override
Disposer addListener(GetStateUpdate listener) {
assert(_debugAssertNotDisposed());
_updaters!.add(listener);
return () => _updaters!.remove(listener);
}
使用示例:
代码
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(); // 当调用增量时,使用update()来更新用户界面上的计数器变量。
}
}
// 在你的Stateless/Stateful类中,当调用increment时,使用GetBuilder来更新Text。
GetBuilder(
init: Controller(), // 首次启动
builder: (_) => Text(
'${_.counter}',
),
)
在 GetBuilder 之外可以通过 Get.find() 获取,但是无法在值变化时自动更新当前组件
class Controller extends GetxController {
/// 你不需要这个,我推荐使用它只是为了方便语法。
/// 用静态方法:Controller.to.increment()。
/// 没有静态方法的情况下:Get.find().increment();
/// 使用这两种语法在性能上没有区别,也没有任何副作用。一个不需要类型,另一个IDE会自动完成。
static Controller get to => Get.find(); // 添加这一行
int counter = 0;
void increment() {
counter++;
update();
}
}
FloatingActionButton(
onPressed: () {
Controller.to.increment(),
}
child: Text("${Controller.to.counter}"),
),
注:通过 Get.find() 获取,并且需要监听值更新,可以使用 Obx
Obx(() => Text("${controller.name}"));
使用技巧
为 GetBuilder 定义 id,controller 中可以根据 id 进行更新
GetBuilder( id: 'text', //这里 init: Controller(), // 每个控制器只用一次 builder: (_) => Text( '${Get.find ().counter}', //here ), ), update(['text']); // 还可以设置另外的条件 update(['text'], counter < 10);
响应的状态管理器
区别:不需要在 controller 中执行 update() 方法,相关组件也会自动更新
将变量或对象变成可观察的 observable
示例:
final name = ''.obs; final isLogged = false.obs; final count = 0.obs; final balance = 0.0.obs; final number = 0.obs; final items =[].obs; final myMap = {}.obs; // 自定义类 - 可以是任何类 final user = User().obs;
使用 Getx 监听相关变量 observer
示例:
// 视图 GetX( builder: (controller) { print("count 1 rebuild"); return Text('${controller.count1.value}'); }, ),
更新 observable 变量
可以直接更新,也可以调用 obs变量的 update 方法进行局部更新
示例:
// 使用 value 去更新
controller.count.value++
// model
// 我们将使整个类成为可观察的,而不是每个属性。
class User{
User({this.name = '', this.age = 0});
String name;
int age;
}
// controller
final user = User().obs;
//当你需要更新user变量时。
user.update( (user) { // 这个参数是你要更新的类本身。
user.name = 'Jonny';
user.age = 18;
});
// 更新user变量的另一种方式。
user(User(name: 'Jo?o', age: 35));
// view
// 可以不使用.value来访问模型值。
user().name;
2333