简述状态管理的原理
使用方法如下:
1 | child: Obx(() => Text( |
widget监听
当使用Obx包装Widget后,child构建会被传入ObxWidget,ObxWidget是StatefulWidget,内部持有一个RxNotifier,用于观察数据变动后回调给当前的state触发setState更新当前的widget
1 | class ObxState extends State<ObxWidget> { |
Rx值绑定
child构建会调用相关obs数据类的.value方法,在获取.value时触发绑定
1 | /// Returns the current [value] |
build中的绑定逻辑
具体的绑定逻辑
1 | abstract class RxInterface<T> { |
总结
Obx包装某个Rx变量后,都会把当前的使用到Rx变量与其包装的Obx绑定起来,当Rx变量变化的时候就会触发Obx的setState更新。
使用中的细节点
是否可以用一个Obx包装根widget,下面的widget调用Rx变量就不用Obx包装了?
根据上述绑定原理,这样做是可行的,确实省略了在下面多次包装Obx的步凑。但是,这种方法的缺点是:当下面用到的任何一个Rx变量更新,都会导致根widget的setState触发,导致整个widget树的刷新,所有的widget都会重新走build方法。
很显然这是不合理的,我们应该控制最小范围刷新才符合状态规范,性能最优。所以我们应该明确自己的widget在绑定哪个Rx字段时需要刷新,并明确调用,而不是刷新所有widget。
我使用Obx包装了某个widget,该widget是通过调用一个方法获取的值,方法中使用了Rx的value值,是否可以绑定成功?
可以的,但需要注意获取值的方法应该随build构建同步调用,也就是说在Obx包装的widget中,获取Rx值的函数是一定被调用的才能绑定成功。
如果widget获取值的方法不是立即执行的,例如是通过一个传入方法来获取的,而该传入方法又不会调用,必须依赖其他状态才会触发调用的情况,就有可能不会绑定成功。
我使用Obx包装了一个StatefulWidget,在StatefulWidget的构造函数中调用了Rx变量值,Obx触发绑定失效了吗?为什么Rx值的变动不能触发widget的更新呢?
不是的,Obx的触发并没有失效,不更新的原因也很简单,StatefulWidget的widget更新由state控制,当我们的state创建后,已经使用widget中的属性初始化过了,所以当Rx值变动,触发Obx刷新时,会调用到其包装的StatefulWidget的didUpdateWidget(covariant Test oldWidget)方法判断是否要通过新的widget来更新state,我们没有在widget覆写该方法,则不会触发state内部字段的改变,所以只会触发state的build方法,如果build方法中有引用widget.xxx的值,那么该值是会更新的。
总结
1.Obx的更新会触发其包装widget的更新,包装widget是否更新则由该widget自己来决定。
一个简单的联动方案是给该statefullWidget一个UniqueKey,那么每次触发state的重建,那么视图也就更新了。实际应用中,不推荐使用此方法,因为创建state是消耗资源的,频繁变动的情况,会影响性能和使用体验。
2.尽量使Rx的值变动影响到最小范围的widget重构。
get_cli
使用get框架后,在创建页面的时候也不用手动去添加各种controller,widget,只需要使用其提供的get_cli即可
install get_cli
安装指令
1 | // To install: |
创建页面相关指令
1 | get create page:home |
更多指令请参考get_cli文档说明