Getx 让 Flutter 更简单
Flutter made easy 这可不是我说的啊,他们的 readme 就是这么写的
虽然他们的文档已经写得很好了,但我还是想专门写点东西
Getx 是个啥
Section titled “Getx 是个啥”这是一个很方便使用的包,让状态管理、依赖注入和路由管理都变得简单多了,而且拿它写 MVVM 体感上和安卓原生是差不多的
当然它最主要的用途还是管理状态(数据),毕竟你也不想拖着InheritedWidget写一大堆模板代码吧
当然管理状态还有像 provider 之类的包,可以都去了解一下,然后看看哪种更合适你(或者是你的项目)
状态管理说着高级,实际上主要还是在不同的 Widget 之间共享变量
简单的基本用法
Section titled “简单的基本用法”现在如果有两个页面 PageA和PageB,它们同时可以修改一个变量count并显示,那我们怎么才能让修改在两个页面间同步呢
聪明的你肯定想到在它们的父组件里面加个InheritedWidget,但是吧每次都要创建这么一个类加上一堆长长的方法名,也太麻烦了
此时 Getx 的 controller就派上用场了,顾名思义它是一个控制器,像ViewModel一样生命周期独立于视图(当然在合适的时机也会自动释放啦)。于是需要共享的变量就可以放在里面
class CountController extend GetxController { int count = 0;}然后在要使用这个变量之前初始化一下这个 controller(这部分涉及 Getx 的依赖管理)
Get.put(CountController()); // 初始化一个 CountController,并将它加入 Getx 的依赖管理器中然后在需要使用这个变量的时候获取这个controller的实例
class PageA extend StatelessWidget { @override Widget build(BuildContext context) {
final controller = Get.find<CountController>(); // 在依赖管理器中找到一个 CountController 对象 print(controller.count);
... }}就这么简单
但还有更方便的,因为我们要把这个count显示出来,所以在它变化时要更新 UI 就得用setState。可是如果我想写响应式呢?当然可以!只需要给这个变量做一点小标记,再在 UI 中略微修改就可以做到了
把count改成下面这样
class CountController extend GetxController { var count = 0.obs;}把界面改成这样
class PageA extend StatelessWidget { @override Widget build(BuildContext context) {
final controller = Get.find<CountController>(); // 在依赖管理器中找到一个 CountController 对象
return Obx(() => Text(controller.count.value.toString())); }}这个Text的内容就会随着count的值改变而改变,妈妈从此再也不用担心我忘记setState了!
不复杂的进阶用法
Section titled “不复杂的进阶用法”.obs 是啥
Section titled “.obs 是啥”给上面的count加上.obs之后,这个变量就是“可观察的”了,也就是 Observable
除了直接加.obs,还可以用Rx<Type>来创建
var count = Rx<Int>(0); // 初始值是不必须的还有一些很常用的类有对应的能快速创建对象的方法
final name = RxString('');final isLogged = RxBool(false);final count = RxInt(0);final balance = RxDouble(0.0);final items = RxList<String>([]);final myMap = RxMap<String, int>({});还没写完呢
解释什么是依赖注入是一件复杂的事,你只需要知道 Getx 提供了一个很好用的依赖管理器:只要你之前把你需要用的对象给放进去,那你就能随时随地,不需要传递什么上下文,在代码的任何一个位置获取到这个对象的实例
当然最多的还是放 Getx 的 Controller:
Controller controller = Get.put(Controller());如果你需要在别的地方用到它,只需要这样:
final controller = Get.find();真是太简单了!
但是很多时候事情没那么简单
Section titled “但是很多时候事情没那么简单”就是说,如果我放了不止一个对象,Getx 又怎么知道我要的是哪个呢?这倒不是难事,因为Get.put()和Get.find()都是能指定类型的,就像这样:
Get.put<MyController>(MyController()); // 这里边的指定不是必须的Get.put<YourController>(YourController());
final someController = Get.find<MyController>();这样就能稳稳地获取到正确的类型了
然后又出现了新的问题:如果我有好多个MyController,又该怎么找到想要的那个呢?
这也很简单,因为Get.put()和Get.find()还可以指定一个 tag:
Get.put<MyController>(MyController(), tag: 'My first Controller');Get.put<MyController>(MyController(), tag: 'My second Controller');
final someController = Get.find<MyController>(tag: 'My first Controller'); // 当然是获取第一个 Controller 啦只要保证 tag 的字符串是唯一的,就能保证一定能获取对应的对象了
下面是官方文档对Get.put()的参数介绍:
Get.put<S>( // 必备:你想得到保存的类,比如控制器或其他东西。 // 注:"S "意味着它可以是任何类型的类。 S dependency
// 可选:当你想要多个相同类型的类时,可以用这个方法。 // 因为你通常使用Get.find<Controller>()来获取一个类。 // 你需要使用标签来告诉你需要哪个实例。 // 必须是唯一的字符串 String tag,
// 可选:默认情况下,get会在实例不再使用后进行销毁 // (例如:一个已经销毁的视图的Controller) // 但你可能需要这个实例在整个应用生命周期中保留在那里,就像一个sharedPreferences的实例或其他东西。 //所以你设置这个选项 // 默认值为false bool permanent = false,
// 可选:允许你在测试中使用一个抽象类后,用另一个抽象类代替它,然后再进行测试。 // 默认为false bool overrideAbstract = false,
// 可选:允许你使用函数而不是依赖(dependency)本身来创建依赖。 // 这个不常用 InstanceBuilderCallback<S> builder,)还有一些别的用法这里就不讲了,因为平常用得比较少,想学的话可以自己去研究 ( ̄﹃ ̄)
官方文档是这么讲的
其实是我懒得写了,反正这些用法五分钟就学得会
其他的好东西
Section titled “其他的好东西”可以像下面这样快速切换应用的语言:
var locale = Locale('en', 'US');Get.updateLocale(locale);可以用Get.context随时获取当前上下文,有一说一这个功能确实有点夸张,但是很多时候能少写一个参数欸