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());
@override
Widget 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());
@override
Widget 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());
@override
Widget 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方法的tag
fenix: 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,如果有多个控制器,就在这实例化多个
// 创建bindings
class MyBinding implements Bindings {
@override
void dependencies() {
Get.lazyPut<MyController>(() => MyController());
// 。。。 其它控制器
}
}
第三步: 绑定到路由中
GetPage(
name: '/binding4',
page: () => MyPage(),
binding: MyBinding(),
),
第四步: UI中使用
使用 Get.find() ,可以处理一个UI中有多个控制器的情况,如果你只有一个控制器,可以选择使用GeView
class MyPage extends StatelessWidget {
@override
Widget 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> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("依赖管理4"),
centerTitle: true,
),
body: Column(
children: [
Text("演示拿到数据:${controller.title}"),
],
),
);
}
}