Flutter状态管理总结(Provider&Get)
2022-08-16 本文已影响0人
woniu
前言:不同状态管理框架的解决思路不一样,从实现上可以分为两大类:
- 通过 Flutter 树机制 解决,例如 Provider;
- 通过 依赖注入,例如 Get。
名称 | 基本原理 |
---|---|
Provide |
依赖树机制,必须基于 context,提供了子组件访问上层的能力 |
Get |
全局单例,任意位置可以存取存在类型重复,内存回收问题 |
一、Provide
基本原理:Flutter 在 BuildContext 类中为我们提供了方法进行向上和向下的查找,provider 正是借助这种树机制,完成了 View -> Presenter (控制器)的获取。所以每次用 Provider 的时候你都会调用 Provider.of<T>(context)。显然,所有 Provider 以下的 Widget 节点,都可以通过自身的 context 访问到 Provider 中的 Presenter,这很好的解决了跨组件的通信问题。
Provider详细分析传送门
二、Get
1、原理分析
树机制很不错,但他依赖于 context,如果层级比较多,会很让人抓狂。get 通过依赖注入的方式,实现了对 Presenter(控制器) 层的获取。简单来说,就是将 Presenter 存到一个单例的 Map 中,这样的好处就是在任何地方都可以获取到,十分的灵活方便,省去了Provide繁杂的中间层处理。
2、单利遇到的问题
全局单例存储一定要考虑到 Presenter 的回收,不然很有可能引起内存泄漏。使用 get 要么你手动在页面 dispose 的时候做 delete 操作,要么你使用 GetBuilder ,其实它里面也是在 dispose 去做了释放。一般情况下,我们会使用GetBuilder。
@override
void dispose() {
super.dispose();
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
// 移除 Presenter 实例
GetInstance().delete<T>(tag: widget.tag);
}
}
3、为什么使用 Provider 的时候不需要考虑这个问题?
重点:这是因为一般页面级别的 Provider 总是跟随 PageRoute。随着页面的退出,整树中的节点都被会回收,所以可以理解为系统机制为我们解决了这个问题。
4、Get相对Provider的优势
4.1 Provider 中我们通过 context实现跨组件访问数据,Provider要想实现跨页面访问那么 Provider 的存储节点需要放在一个更高的位置,但同样需要注意回收的处理。
4.2 Get 因为是全局单例,无论是跨页面或者跨组件,都没有任何依赖。所以,Get的使用更加快捷、方便。所以,在多个跨组件业务中更加推荐使用Get,摆脱Provider的context依赖。
5、控制刷新范围
5.1 get 的 Obx 组件使用极为方便简洁,调用如下:
class Home extends StatelessWidget {
var count = 0.obs;
@override
Widget build(context) => Scaffold(
body: Center(
child: Obx(() => Text("$count")),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => count ++,
));
}
5.2 分析起来就三步
/// 申明变量,进行obs监听
var count = 0.obs;
/// 响应组件
Obx(() => Text("$count"))
/// 变量修改,同步 Obx 变化
count ++
6、为什么obs能监听到改变
原因就是obs 这个扩展方法会返回一个 RxInt 类型的对象,这种对象核心在于他的 get 和 set 方法。内部添加了监听addListener,所以能随时监听到数据的改变。