Flutter学习-GetX-05 生命周期
本文主要介绍下Getx中关于值的生命周期和状态管理的生命周期
之前介绍了关于依赖注入的2种方式,可以是直接创建或者懒加载的方式。这里关于控制器共享的情况:
Class a => Class B (has controller X) => Class C (has controller X)
在A类中,控制器还没有进入内存,因为你还没有使用它(Get是懒加载)。在类B中,你使用了控制器,并且它进入了内存。在C类中,你使用了与B类相同的控制器,Get会将控制器B的状态与控制器C共享,同一个控制器还在内存中。
如果你关闭C屏和B屏,Get会自动将控制器X从内存中移除,释放资源,因为a类没有使用该控制器。如果你再次导航到B,控制器X将再次进入内存,如果你没有去C类,而是再次回到a类,Get将以同样的方式将控制器从内存中移除。 如果类C没有使用控制器,你把类B从内存中移除,就没有类在使用控制器X,同样也会被处理掉。
唯一能让Get乱了阵脚的例外情况,是如果你意外地从路由中删除了B,并试图使用C中的控制器,在这种情况下,B中的控制器的创建者ID被删除了,Get被设计为从内存中删除每一个没有创建者ID的控制器。如果你打算这样做,在B类的GetBuilder中添加 "autoRemove: false "标志,并在C类的GetBuilder中使用adopID = true;
1. 值的生命周期
之前介绍Obx和GetX等中其中Workers是监听值的生命周期,Workers将协助你在事件发生时触发特定的回调。
///每次`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));
所有worker都会返回一个Worker实例,你可以用它来取消(通过dispose())worker。
ever:每当 Rx 变量发出一个新的值时,就会被调用。everAll:和ever很像,但它需要一个 Rx 值的List,每次它的变量被改变时都会被调用。就是这样。once:once只在变量第一次被改变时被调用。debounce:debounce在搜索函数中非常有用,你只希望API在用户完成输入时被调用。如果用户输入 "Jonny",你将在API中进行5次搜索,分别是字母J、o、n、n和y。使用Get不会发生这种情况,因为你将有一个"debounce "Worker,它只会在输入结束时触发。interval:interval 与 debouce不同,debouce如果用户在1秒内对一个变量进行了1000次修改,他将在规定的计时器(默认为800毫秒)后只发送最后一次修改。Interval则会忽略规定时间内的所有用户操作。如果你发送事件1分钟,每秒1000个,那么当用户停止DDOS事件时,debounce将只发送最后一个事件。建议这样做是为了避免滥用,在用户可以快速点击某样东西并获得一些好处的功能中(想象一下,用户点击某样东西可以赚取硬币,如果他在同一分钟内点击300次,他就会有300个硬币,使用间隔,你可以设置时间范围为3秒,无论是点击300次或100万次,1分钟内他最多获得20个硬币)。debounce适用于防DDOS,适用于搜索等功能,每次改变onChange都会调用你的api进行查询。Debounce会等待用户停止输入名称,进行请求。如果在上面提到的投币场景中使用它,用户只会赢得1个硬币,因为只有当用户暂停到既定时间时,它才会被执行。
注意:Worker应该总是在启动Controller或Class时使用,所以应该总是在onInit(推荐)、Class构造函数或StatefulWidget的initState(大多数情况下不推荐这种做法,但应该不会有任何副作用)。
class GetXHomeController extends GetxController {
var count = 0.obs;
add(){
count.value++;
}
@override
void onInit() {
super.onInit();
ever(count, (callback) => print('ever:${count.value}'));
once(count, (callback) => print('once${count.value}'));
debounce(count, (callback) => print('debounce${count.value}'),time: const Duration(seconds: 1));
}
}
用于一些搜索处理,或者点击频率处理。
2. contrlller的生命周期
GetBuilder替代StatefulWidget
在开发中我们可能会在Widget初始化的时候做些操作比如请求数据,如果是StatefulWidget则在initState中进行创建请求。或者在dispose()中调用某些方法。现在可以在GetBuilder中进行操作
GetBuilder<Controller>(
initState: (_) => Controller.to.fetchApi(),
dispose: (_) => Controller.to.closeStreams(),
builder: (s) => Text('${s.username}'),
),
但是最好还是在控制器中做相对应的操作
@override
void onInit() {
fetchApi();
super.onInit();
}
///关闭流用onClose方法,而不是dispose
@override
void onClose() {
user.close();
name.close();
super.onClose();
}
onInit类似我们iOS中的viewDidLoad,onClose则类似dealloc方法
控制器的生命周期。
onInit()是创建控制器的地方。onReady()在创建成功后马上调用onClose(),关闭控制器,为删除方法做准备。deleted: 你不能访问这个API,因为它实际上是将控制器从内存中删除。它真的被删除了,不留任何痕迹。
3. 小结
针对值的生命周期和contrrller的生命周期我们选择在合适的时机使用对应的方法,其中如果我们想要达到页面返回是刷新,或者请求可以通过 var result = await Get.toNamed()拿到结果进行操作。
转载自:https://juejin.cn/post/7127647120374366221