GetX

Posted by アライさん on 2021年07月28日

GetBuilder、GetX、Obx

  • GetBuilder在RAM中最高效,但需要手动调用update()刷新,并且所有GetBuilder同一个Controller的地方都会被重建。
  • GetX比GetBuilder消耗内存多一些,无需调用update()刷新,并且只有自己使用的值变化了才会rebuild。有越多的 “单独 “部件,GetX的性能就越突出。

一、响应式状态管理

有越多的 “单独 “部件,GetX的性能就越突出!

响应式状态管理,使用.obs,配合GetX、Obx使用

响应式编程对RAM的消耗比较大

使用响应式状态管理,Controller无须手动调用update()去更新,widget会自动更新。

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Class MyController extends GetxController{
///除obs之外,也可以使用Rx<Type>或Rx{Type}
///final name = Rx<String>('');
///final name = RxString('');
final number = 0.obs;
final items = <String>[].obs;
final myMap = <String, int>{}.obs;

setNumber(int number){
this.number.value = number;
}

///与setUserName2相同,另一种方法
setUserName1({required String name}){
user.update((user){
user.name = name;
});
}
///与setUserName1相同,另一种方法
setUserName2({required String name}){
user(User(name:name,age:user.value.age));
}
}

View

1
2
3
4
5
6
7
8
9
///使用GetX的方法,将直接绑定具体的值,如myController.name,其他属性更改不会引起重建
GetX<MyController>(
init: MyController(),
builder: (myController) {
return Text(
myController.name.value,
);
},
),
1
2
3
4
5
6
7
MyController myController = Get.put(MyController());
///使用Obx的方法,将直接绑定具体的值,如myController.name,其他属性更改不会引起重建
Obx(() {
return Text(
myController.name.value,
);
}),

List

对list进行插入删除操作,会自动重建使用它的widget。

且调用list的属性不需要用.value

1
2
3
4
//controller中
final list = List<User>().obs;
//widget中,不需要.value
controller.list.length;

Workers

1
2
3
4
5
6
7
8
9
10
11
///每次Rx变量发出一个新值时,即`count1`变化时调用。
ever(count1, (_) => print("$_ has been changed"));

///只有在变量$_第一次被改变时才会被调用。
once(count1, (_) => print("$_ was changed once"));

///防DDos - 每当用户停止输入1秒时调用,例如。
debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));

///忽略1秒内的所有变化。
interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));

二、简单状态管理

对CPU影响最小,已经尽可能花费最少的资源。

简单状态管理使用GetBuilder,修改配合update()进行更新,如果要只rebuild指定属性,需要指定id。

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class MyController extends GetxController{
final number = 0;
final items = <String>[];
final myMap = <String, int>{};

setNumber(int number){
this.number.value = number;

//rebuild所有绑定了MyController的组件
//update();

//当number>10时,将会rebuild id为number的所有widget
//update(['number'],number>10);

//将会rebuild id为number的所有widget
update(['number']);

}
}

View

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
///使用GetBuilder的方式,需要配合MyController中的update(),
///一旦调用update(),所有GetBuilder<MyController>的界面都会刷新,类似provider
GetBuilder<MyController>(
init: MyController(), // 首次启动,如果已经由其他路由创建,就不需要
builder: (_) => Text(
'${_.counter}',
),
),

GetBuilder<MyController>(
id: 'counter', //设置id,用update(['counter'])来更新这个id的widget
init: MyController(), // 首次启动,如果已经由其他路由创建,就不需要
builder: (_) => Text(
'${_.counter}',
),
),

三、其他地方使用

如果需要在GetBuilder之外,使用Controller,可以用

1
2
MyController controller = Get.find<MyController>();
controller.setNumber(10);

其他

  • Get被设计为从内存中删除每一个没有创建者ID的控制器。
    如果你打算这样做,在B类的GetBuilder中添加 “autoRemove: false “标志,并在C类的GetBuilder中使用adopID = true;

  • 一般不需要StatefulWidget,除非需要使用混合器如TickerProviderStateMixin。
    需要init和dispose,可以使用GetBuilder中的initState与dispose。
    更好的做法是使用Controller中的onInit\

  • 一般来说,对于大多数场景都是可以使用响应式变量的。

    但是,在一个包含了大量对象的List,都使用响应式变量,将生成大量的StreamBuilder,必将对内存造成较大的压力,该情况下,就要考虑使用简单状态管理了