1.Getx 依赖管理

这东西你可以理解为,把controller 和 路由进行分离, 然后由它负责沟通控制器和UI, 同时使用依赖的方式管理的控制器只需在某个页面中实例化一次,其它页面就可以直接使用,而不需要再实例化一次

仓库文档参考

1.1 如何使用依赖管理

代码在 binding/demo01 下

第一步:创建控制器

  1. // 控制器
  2. class GoodsController extends GetxController {
  3. final _goods = ["橘子", "apple", "pear"];
  4. List<String> get goods => _goods;
  5. }

第二步:创建视图UI

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:getx_demo/binding/demo1/goods_controller.dart';
  4. import 'package:getx_demo/binding/demo2/list_controller.dart';
  5. class GoodsPage extends StatelessWidget {
  6. //使用 Get.put 处理依赖管理
  7. final GoodsController controller = Get.put(GoodsController());
  8. @override
  9. Widget build(BuildContext context) {
  10. return Scaffold(
  11. appBar: AppBar(
  12. title: Text("依赖管理"),
  13. centerTitle: true,
  14. ),
  15. body: Column(
  16. children: [
  17. Row(
  18. children: controller.goods.map((item) => Text("$item,")).toList(),
  19. ),
  20. ],
  21. ),
  22. );
  23. }
  24. }
  • Get.put(), 可以让你的控制器 在 Get 实例中实例化类,这将使它在整个应用程序中可用,也就是说你使用这种方法,实例化的数据源,可以在全局每个页面中使用

1. 2 对比两种方式实例化的控制器

代码在 binding/demo02 下

  • 【直接实例化控制器和】 和 Get.put()方式的实例化的控制器

第一步: 创建控制器 - ListController

  1. class ListController extends GetxController {
  2. final _animals = ["黑猫", "抱狗", "小驴"];
  3. List<String> get lists => _animals;
  4. }

第二步: 创建控制器 - GoodsController

  1. class GoodsController extends GetxController {
  2. final _goods = ["橘子", "apple", "pear"];
  3. List<String> get goods => _goods;
  4. }

第三步: 创建UI - ListPage

  1. class ListPage extends StatelessWidget {
  2. // 直接实例化
  3. final ListController controller = ListController();
  4. final GoodsController goodsController = Get.put(GoodsController());
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. title: Text("依赖管理"),
  10. centerTitle: true,
  11. ),
  12. body: Column(
  13. children: [
  14. Text("渲染ListController的数据"),
  15. Row(
  16. children: controller.lists.map((item) => Text("$item, ")).toList(),
  17. ),
  18. SizedBox(height: 50),
  19. Text("渲染GoodsController的数据"),
  20. Row(
  21. children:
  22. goodsController.goods.map((item) => Text("$item, ")).toList(),
  23. )
  24. ],
  25. ),
  26. );
  27. }
  28. }

两种方式没有发现啥区别,都渲染出来了数据

第四步: 使用Get.find() 查找控制器

记得再控制器那章中提到了 Get.find() ,它可以帮你找到控制器,不过那时候,只是提了一下,其实这个东西也是有限制的, 这东西就找不到你直接实例化的控制器, 而只能找到通过 依赖注入 这种方式实例化的控制器

  1. class ListPage extends StatelessWidget {
  2. // 直接实例化
  3. final ListController controller = ListController();
  4. final GoodsController goodsController = Get.put(GoodsController());
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. title: Text("依赖管理"),
  10. centerTitle: true,
  11. ),
  12. body: Column(
  13. children: [
  14. Text("渲染ListController的数据"),
  15. Row(
  16. children: controller.lists.map((item) => Text("$item, ")).toList(),
  17. ),
  18. SizedBox(height: 50),
  19. Text("渲染GoodsController的数据"),
  20. Row(
  21. children:
  22. goodsController.goods.map((item) => Text("$item, ")).toList(),
  23. ),
  24. SizedBox(height: 50),
  25. Text("通过Get.find查找GoodsController"),
  26. Row(
  27. children: Get.find<GoodsController>()
  28. .goods
  29. .map((item) => Text("$item, "))
  30. .toList(),
  31. ),
  32. // 以下报错 【ListController not found, you need to call Get.put() 】
  33. SizedBox(height: 50),
  34. Text("通过Get.find查找ListController"),
  35. Row(
  36. children: Get.find<ListController>()
  37. .lists
  38. .map((item) => Text("$item, "))
  39. .toList(),
  40. )
  41. ],
  42. ),
  43. );

以上代码,前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,
  1. Get.put<LoginController>(LoginController(), permanent: true);

代码在 binding/demo03 下

  1. final controller = Get.put<StaffController>(
  2. StaffController(),
  3. tag: "staff1",
  4. permanent: true,
  5. );
  6. final StaffController controller2 = Get.put(
  7. StaffController(),
  8. tag: "staff2",
  9. );

1.4 Get.lazyPut()参数

使用它添加的依赖项是惰性的,它只有在使用时才会被实例化,用法同Get.put()

用法:

  1. Get.lazyPut<ApiMock>(() => ApiMock());
  2. // 传入其它参数
  3. Get.lazyPut<FirebaseAuth>(
  4. () {
  5. return FirebaseAuth();
  6. },
  7. tag: "tag", // 同put方法的tag
  8. fenix: true // 类似于“permanent”,区别在于实例在不使用时被回收,但当需要再次使用时,会重新创建实例,默认false
  9. )

Permanent 和 fenix 之间的根本区别在于存储实例的方式

1.5 Get.putAsync 注册异步实例

文档不详,找不到demo

1.6 Get.create()

  • 用法同 Get.put()
  1. Get.Create<SomeClass>(() => SomeClass());
  2. 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

第一步: 创建一个控制器

  1. class MyController extends GetxController {
  2. final _works = ["保洁", "月嫂", "育婴师"];
  3. final _nums = ["1", "2", "3"];
  4. List<String> get works => _works;
  5. List<String> get nums => _nums;
  6. }

第二步: 创建一个类并实现 Binding,如果有多个控制器,就在这实例化多个

  1. // 创建bindings
  2. class MyBinding implements Bindings {
  3. @override
  4. void dependencies() {
  5. Get.lazyPut<MyController>(() => MyController());
  6. // 。。。 其它控制器
  7. }
  8. }

第三步: 绑定到路由中

  1. GetPage(
  2. name: '/binding4',
  3. page: () => MyPage(),
  4. binding: MyBinding(),
  5. ),

第四步: UI中使用

使用 Get.find() ,可以处理一个UI中有多个控制器的情况,如果你只有一个控制器,可以选择使用GeView

  1. class MyPage extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text("依赖管理4"),
  7. centerTitle: true,
  8. ),
  9. body: Column(
  10. children: [
  11. Text("演示tag参数"),
  12. Row(
  13. children: Get.find<MyController>()
  14. .works
  15. .map((item) => Text("$item"))
  16. .toList(),
  17. )
  18. ],
  19. ),
  20. );
  21. }
  22. }

2.1 使用GetView代替StatelessWidget

  • 可以直接使用 controller.变量 调用
  1. class MyPage extends GetView<MyController> {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text("依赖管理4"),
  7. centerTitle: true,
  8. ),
  9. body: Column(
  10. children: [
  11. Text("演示拿到数据:${controller.title}"),
  12. ],
  13. ),
  14. );
  15. }
  16. }