1.Getx 依赖管理
这东西你可以理解为,把controller 和 路由进行分离, 然后由它负责沟通控制器和UI, 同时使用依赖的方式管理的控制器只需在某个页面中实例化一次,其它页面就可以直接使用,而不需要再实例化一次
1.1 如何使用依赖管理
第一步:创建控制器
// 控制器class GoodsController extends GetxController {final _goods = ["橘子", "apple", "pear"];List<String> get goods => _goods;}
第二步:创建视图UI
import 'package:flutter/material.dart';import 'package:get/get.dart';import 'package:getx_demo/binding/demo1/goods_controller.dart';import 'package:getx_demo/binding/demo2/list_controller.dart';class GoodsPage extends StatelessWidget {//使用 Get.put 处理依赖管理final GoodsController controller = Get.put(GoodsController());@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("依赖管理"),centerTitle: true,),body: Column(children: [Row(children: controller.goods.map((item) => Text("$item,")).toList(),),],),);}}
- Get.put(), 可以让你的控制器 在 Get 实例中实例化类,这将使它在整个应用程序中可用,也就是说你使用这种方法,实例化的数据源,可以在全局每个页面中使用
1. 2 对比两种方式实例化的控制器
- 【直接实例化控制器和】 和 Get.put()方式的实例化的控制器
第一步: 创建控制器 - ListController
class ListController extends GetxController {final _animals = ["黑猫", "抱狗", "小驴"];List<String> get lists => _animals;}
第二步: 创建控制器 - GoodsController
class GoodsController extends GetxController {final _goods = ["橘子", "apple", "pear"];List<String> get goods => _goods;}
第三步: 创建UI - ListPage
class ListPage extends StatelessWidget {// 直接实例化final ListController controller = ListController();final GoodsController goodsController = Get.put(GoodsController());@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("依赖管理"),centerTitle: true,),body: Column(children: [Text("渲染ListController的数据"),Row(children: controller.lists.map((item) => Text("$item, ")).toList(),),SizedBox(height: 50),Text("渲染GoodsController的数据"),Row(children:goodsController.goods.map((item) => Text("$item, ")).toList(),)],),);}}
两种方式没有发现啥区别,都渲染出来了数据
第四步: 使用Get.find() 查找控制器
记得再控制器那章中提到了 Get.find() ,它可以帮你找到控制器,不过那时候,只是提了一下,其实这个东西也是有限制的, 这东西就找不到你直接实例化的控制器, 而只能找到通过 依赖注入 这种方式实例化的控制器
class ListPage extends StatelessWidget {// 直接实例化final ListController controller = ListController();final GoodsController goodsController = Get.put(GoodsController());@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("依赖管理"),centerTitle: true,),body: Column(children: [Text("渲染ListController的数据"),Row(children: controller.lists.map((item) => Text("$item, ")).toList(),),SizedBox(height: 50),Text("渲染GoodsController的数据"),Row(children:goodsController.goods.map((item) => Text("$item, ")).toList(),),SizedBox(height: 50),Text("通过Get.find查找GoodsController"),Row(children: Get.find<GoodsController>().goods.map((item) => Text("$item, ")).toList(),),// 以下报错 【ListController not found, you need to call Get.put() 】SizedBox(height: 50),Text("通过Get.find查找ListController"),Row(children: Get.find<ListController>().lists.map((item) => Text("$item, ")).toList(),)],),);
以上代码,前3个都通过,就最后一个会报错
“ListController” not found. You need to call “Get.put(ListController())” or “Get.lazyPut(()=>ListController())”
所以直接实例化控制器的这种是不能全局使用的,只能在当前实例化的这个页面中使用
报错提示
上边的报错中,可以看到,提示语中还有个 Get.lazyPut() 方法,此方法功能和用法和Get.put()是一样的,不同的是一个put是立马实例化,lazyPut 是在用到的时候才会实例化 ,
1.3 Get.put参数
Get.put() 除了必填参数外,还有2个常用可选命名参数,tag 和 permanent
- 必填参数:Get.put(SomeClass());
- 可选参数tag: Get.put(Controller, tag: “string”); 和前边说的GetBuild中传入的id差不多
- 可选参数permanent: 这个就比较重要了,设置为true,可以将实例保存在内存中并持久化保存,不会被get销毁, 默认是false, 该参数再有些场景下很有用,比如路由跳转时,你可能就拿不到有些controller,这时候就可以把你拿不到的controller 设置成 true,
Get.put<LoginController>(LoginController(), permanent: true);
代码在 binding/demo03 下
final controller = Get.put<StaffController>(StaffController(),tag: "staff1",permanent: true,);final StaffController controller2 = Get.put(StaffController(),tag: "staff2",);
1.4 Get.lazyPut()参数
使用它添加的依赖项是惰性的,它只有在使用时才会被实例化,用法同Get.put()
用法:
Get.lazyPut<ApiMock>(() => ApiMock());// 传入其它参数Get.lazyPut<FirebaseAuth>(() {return FirebaseAuth();},tag: "tag", // 同put方法的tagfenix: true // 类似于“permanent”,区别在于实例在不使用时被回收,但当需要再次使用时,会重新创建实例,默认false)
Permanent 和 fenix 之间的根本区别在于存储实例的方式
1.5 Get.putAsync 注册异步实例
文档不详,找不到demo
1.6 Get.create()
- 用法同 Get.put()
Get.Create<SomeClass>(() => SomeClass());Get.Create<LoginController>(() => LoginController());
1.7 对比 permanent 和 fenix
permanent 是 Get.put() 的命名参数
fenix 是 Get.lazyPut() 的命名参数
区别: Permanent 和 fenix 之间的根本区别在于存储实例的方式,默认情况下,GetX 在实例不使用时删除它们。这意味着: 如果屏幕1有控制器1,屏幕2有控制器2,并且您从堆栈中删除了第一个路由(如果您使用 Get.off ()或 Get.offNamed ()) ,则控制器1将失去其使用,因此它将被删除。
选择使用 permanent: true,那么控制器在这个转换中不会丢失——这对于希望在整个应用程序中保持控制器是活动的非常有用。
fenix:true,你不用担心在屏幕更改之间丢失它将处理未使用的控制器,但是当您需要它时,它将“从内存中重新创建”一个新实例,不需要时,会被get回收,也就可能会频繁的重新创建实例
1.8 Get.create() 对比 Get.put() 和 Get.lazyPut()
Get.create() 创建的控制器,默认是它有永久性的,不会在屏幕之间丢失它,而且创建的实例是非共享的实例,意思就是每次创建的都是新的实例,互相不影响,您希望为该列表创建一个唯一的实例——因此,Get.create 必须与 GetWidget 一起使用,【GetWidget 后边说,是用来代替 StateLessWidget的】
Get.put() 和 Get.lazyPut() 创建的都是同一实例,数据会互相影响,一变全变
2. Bindings 绑定
Binding 类是一个将依赖注入进行分离,同时“绑定”到 状态管理器Controller 和 路由管理器中,简单说,就是把UI 中的 控制器实例化部分抽离出来了,抽离时需要实现 Bindings 类
2.1 如何使用Bindings
第一步: 创建一个控制器
class MyController extends GetxController {final _works = ["保洁", "月嫂", "育婴师"];final _nums = ["1", "2", "3"];List<String> get works => _works;List<String> get nums => _nums;}
第二步: 创建一个类并实现 Binding,如果有多个控制器,就在这实例化多个
// 创建bindingsclass MyBinding implements Bindings {@overridevoid dependencies() {Get.lazyPut<MyController>(() => MyController());// 。。。 其它控制器}}
第三步: 绑定到路由中
GetPage(name: '/binding4',page: () => MyPage(),binding: MyBinding(),),
第四步: UI中使用
使用 Get.find() ,可以处理一个UI中有多个控制器的情况,如果你只有一个控制器,可以选择使用GeView
class MyPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("依赖管理4"),centerTitle: true,),body: Column(children: [Text("演示tag参数"),Row(children: Get.find<MyController>().works.map((item) => Text("$item")).toList(),)],),);}}
2.1 使用GetView代替StatelessWidget
- 可以直接使用
controller.变量调用
class MyPage extends GetView<MyController> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("依赖管理4"),centerTitle: true,),body: Column(children: [Text("演示拿到数据:${controller.title}"),],),);}}
