Flutter状态管理神器之GetX探究?
高效学习模型
- what-->why-->how 模型
- 是什么?-->为什么使用?-->如何使用?-->实现原理-->总结分享(学以致用)
一.GetX是什么?
-
GetX 是 Flutter 上的一个轻量且强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理。
-
GetX 有3个基本原则:
- 性能: GetX 专注于性能和最小资源消耗。GetX 打包后的apk占用大小和运行时的内存占用与其他状态管理插件不相上下。性能测试实例: 性能测试。
- 效率: GetX 的语法非常简捷,并保持了极高的性能,能极大缩短开发时长。
- 结构: GetX 可以将界面、逻辑、依赖和路由完全解耦,用起来更清爽,逻辑更清晰,代码更容易维护。
-
GetX 并不臃肿,却很轻量。如果只使用状态管理,只有状态管理模块会被编译,其他没用到的东西都不会被编译到你的代码中。它拥有众多的功能,但这些功能都在独立的容器中,只有在使用后才会启动。
-
Getx有一个庞大的生态系统,能够在Android、iOS、Web、Mac、Linux、Windows和你的服务器上用同样的代码运行。 通过Get Server 可以在你的后端完全重用你在前端写的代码。
二. 为什么使用GetX?
-
Flutter更新后,很多时候很多包都会坏掉。有时会发生编译错误,经常出现的错误,至今仍没有答案,开发者需要知道错误的来源,跟踪错误,才会尝试在相应的仓库中开一个问题,并看到其问题的解决。 GetX集中了开发的主要资源(状态、依赖和路由管理),可以在pubspec中添加一个包,然后开始工作。Flutter更新后,唯一需要做的就是更新Get依赖,然后开始工作。Get还可以解决兼容性问题。例如: 一个包的版本与另一个包的版本不兼容,因为一个包在一个版本中使用了依赖,而另一个包在另一个版本中使用了依赖?使用Get也不用担心这个问题,因为所有的东西都在同一个包里,是完全兼容的。
-
Flutter很简单,也很不可思议,但是Flutter仍然有一些代码,对于大多数开发者来说可能是不需要的,比如
Navigator.of(context).push (context, builder [...]
,写了8行代码仅仅只为了调用一个路由。而使用Get只需Get.to(Home())
就完成了。动态网页URL是目前Flutter中非常痛苦的一件事,而用GetX则非常简单。在Flutter中管理状态,管理依赖关系也产生了很多讨论,因为pub中的模式有上百种。但是没有什么比在你的变量末尾加一个".obs "更简单的了,把你的widget放在一个Obx里面,就这样,所有对这个变量的更新都会在页面上自动更新。 -
轻松,不用担心性能。Flutter的性能已经很惊人了,但是想象一下,使用一个状态管理器,和一个定位器来分布你的blocs/stores/controllers/等等类。当你不需要那个依赖的时候,你必须手动调用排除它。但是,你有没有想过简单地使用你的控制器,当它不再被任何人使用时,它会简单地从内存中删除?这就是GetX所做的。有了SmartManagement,所有不被使用的东西都会从内存中删除,除了编程,您不应该担心任何事情。GetX将保证您消耗的是最低限度的必要资源,甚至没有为此创建一个逻辑。
-
实际解耦。你可能听说过 "将界面与业务逻辑分离 "的概念。这并不是BLoC、MVC、MVVM的特例,市面上的其他标准都有这个概念。但是,由于使用了上下文(context),这个概念在Flutter中往往可以得到缓解。 如果你需要上下文来寻找InheritedWidget,你需要在界面中找到它,或者通过参数传递上下文。我特别觉得这种解决方案非常丑陋,要在团队中工作,我们总会对View的业务逻辑产生依赖。Getx与标准的做法不一样,虽然它并没有完全禁止使用StatefulWidgets、InitState等,但它总有类似的方法,可以更干净。控制器是有生命周期的,例如当你需要进行APIREST请求时,你不依赖于界面中的任何东西。你可以使用onInit来启动http调用,当数据到达时,变量将被填充。由于GetX是完全响应式的(真的,在流下工作),一旦项目被填充,所有使用该变量的widgets将在界面中自动更新。这使得具有UI专业知识的人只需要处理widget,除了用户事件(比如点击按钮)之外,不需要向业务逻辑发送任何东西,而处理业务逻辑的人将可以自由地单独创建和测试业务逻辑。
对 Flutter 比较流行的状态管理插件做对比分析结果如下:
1. 横向对比参数
横向分析对比,综合了 pub 的喜欢数(Likes)、流行度(Popularity)和得分(Pub Points),Gitbub的 Star 数、贡献者数量五个维度进行比对。各个参数说明如下:
-
喜欢数(Likes) :反映的是该插件受 Flutter 开发者的喜好程度,间接反映了插件的文档完整性、可读性和插件的易用性;
-
流行度(Popularity) :反映的是该插件受 Flutter 开发者的欢迎程度和插件应用的广泛性(白话解释:使用人的人越多,意味着有更多的人提前帮你踩坑💣)。
-
得分(Pub Points) :pub 的得分满分是130分,其实是对插件的一个比较基础的全面评测,分为如下6个部分:
- 遵循插件规范(20分)
- 文档完整性(20分)
- 跨平台支持(20分)
- 通过静态分析(30分)
- 版本兼容性(20分)
- 支持 null safety(20分)
-
GitHub Star 数:这个大家都懂,反映的是受开发者认可的程度,实力的象征!
-
贡献者数量:这个其实就是插件的社区号召力和参与维护的人数,贡献者越多也意味着插件的可靠性越高,不至于说更新过慢或突然中止维护(中止维护属于天坑了💣💣💣)。
为了统一对比尺度,我们统一按与本篇列出的管理插件同维度最大值进行比对,根据比值得出星级,共设置5颗星,比值与星级对应关系如下:
- 0.9-1.0:5星
- 0.8-0.9:4星
- 0.6-0.8:3星
- 0.3-0.6:2星
- 0.3以下:1星
2. 业界优秀状态管理插件对比分析
GetX:
Provider:
BloC:
Fish Redux:
各项参数星级评定如下:
插件名称 | 喜欢数 | 流行度(%) | 得分 | Star 数 | 贡献者数量
排行榜
基于上面的星级评定和数据,把每项数据的比值求和,从大大小排序,得到的分值和排行榜如下:
插件名称 | 排名 | 综合评分 | 星级 |
三. 如何使用GetX ?
三大优势功能
状态管理
目前,Flutter有几种状态管理器。但是,它们中的大多数都涉及到使用ChangeNotifier来更新widget,这对于中大型应用的性能来说是一个很糟糕的方法。可以在Flutter的官方文档中查看到,ChangeNotifier应该使用1个或最多2个监听器,这使得它们实际上无法用于任何中等或大型应用。
Get 并不是比任何其他状态管理器更好或更差,而是说你应该分析这些要点以及下面的要点来选择只用Get,还是与其他状态管理器结合使用。
Get不是其他状态管理器的敌人,因为Get是一个微框架,而不仅仅是一个状态管理器,既可以单独使用,也可以与其他状态管理器结合使用。
Get有两个不同的状态管理器:简单的状态管理器(GetBuilder)和响应式状态管理器(GetX)。
响应式状态管理器
响应式编程可能会让很多人感到陌生,因为觉得它很复杂,但是GetX将响应式编程变得非常简单。
- 你不需要创建StreamControllers.
- 你不需要为每个变量创建一个StreamBuilder。
- 你不需要为每个状态创建一个类。
- 你不需要为一个初始值创建一个get。
使用 Get 的响应式编程就像使用 setState 一样简单。
让我们想象一下,你有一个名称变量,并且希望每次你改变它时,所有使用它的小组件都会自动刷新。
这就是你的计数变量。
var name = 'Jonatas Borges';
要想让它变得可观察,你只需要在它的末尾加上".obs"。
var name = 'Jonatas Borges'.obs;
而在UI中,当你想显示该值并在值变化时更新页面,只需这样做。
Obx(() => Text("${controller.name}"));
这就是全部,就这么简单。
关于状态管理的更多细节
关于状态管理更深入的解释请查看这里。在那里你将看到更多的例子,以及简单的状态管理器和响应式状态管理器之间的区别。
路由管理
如果你想免上下文(context)使用路由/snackbars/dialogs/bottomsheets,GetX对你来说也是极好的:
在MaterialApp前加上 "Get",把它变成GetMaterialApp。
GetMaterialApp( // Before: MaterialApp(
home: MyHome(),
)
导航到新页面
Get.to(NextScreen());
用别名导航到新页面。查看更多关于命名路由的详细信息这里
Get.toNamed('/details');
要关闭snackbars, dialogs, bottomsheets或任何你通常会用Navigator.pop(context)关闭的东西。
Get.back();
进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)。
Get.off(NextScreen());
进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)。
Get.offAll(NextScreen());
注意到你不需要使用context来做这些事情吗?这就是使用Get路由管理的最大优势之一。有了它,你可以在你的控制器类中执行所有这些方法,而不用担心context在哪里。
关于路由管理的更多细节
关于别名路由,和对路由的低级控制,请看这里。
依赖管理
Get有一个简单而强大的依赖管理器,它允许你只用1行代码就能检索到与你的Bloc或Controller相同的类,无需Provider context,无需inheritedWidget。
Controller controller = Get.put(Controller()); // 而不是 Controller controller = Controller();
- 注意:如果你使用的是Get的状态管理器,请多注意绑定api,这将使你的界面更容易连接到你的控制器。
你是在Get实例中实例化它,而不是在你使用的类中实例化你的类,这将使它在整个App中可用。 所以你可以正常使用你的控制器(或类Bloc)。
提示: Get依赖管理与包的其他部分是解耦的,所以如果你的应用已经使用了一个状态管理器(任何一个,都没关系),你不需要全部重写,你可以使用这个依赖注入。
controller.fetchApi();
想象一下,你已经浏览了无数条路由,现在你需要拿到一个被遗留在控制器中的数据,那你需要一个状态管理器与Provider或Get_it一起使用来拿到它,对吗?用Get则不然,Get会自动为你的控制器找到你想要的数据,而你甚至不需要任何额外的依赖关系。
Controller controller = Get.find();
//是的,它看起来像魔术,Get会找到你的控制器,并将其提供给你。你可以实例化100万个控制器,Get总会给你正确的控制器。
然后你就可以恢复你在后面获得的控制器数据。
Text(controller.textFromApi);
关于依赖管理的更多细节
关于依赖管理的更深入解释请看此处。
纸上得来终觉浅,绝知此事要躬行 代码敲起来
计数器实例如下:
view
logic
代码是如此的简洁及so easy 共不到10行代码实现该功能 是其他插件及原生所不及的
四. GetX原理 --待实现
五. 总结分享(学以致用) --待实现
转载自:https://juejin.cn/post/7021163730004082719