Getx - 如何使用依赖管理和Bindings

1.Getx 依赖管理

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

仓库文档参考

1.1 如何使用依赖管理

代码在 binding/demo01 下

第一步:创建控制器

// 控制器
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 对比两种方式实例化的控制器

代码在 binding/demo02 下

  • 【直接实例化控制器和】 和 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个都通过,就最后一个会报错
在这里插入图片描述
所以直接实例化控制器的这种是不能全局使用的,只能在当前实例化的这个页面中使用

报错提示

上边的报错中,可以看到,提示语中还有个 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}"),
        ],
      ),
    );
  }
}
  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用 GetX 库中的 Obx 方法时,可以使用 async 和 await 实现异步操作。 例如,在一个 Obx 函数中调用一个异步函数,并使用 await 关键字等待返回结果: ``` final myValue = Obx(() async { var value = await someAsyncFunction(); return value; }); ``` 在这个例子中,someAsyncFunction() 是一个异步函数,Obx 包装了它并返回一个 Obx 对象。 当 someAsyncFunction() 返回时,Obx 会自动刷新并通知所有依赖它的 widgets 进行更新。 需要注意,在 Obx 中使用 await 的情况,需要确保 Obx 函数是 async 的。 ### 回答2: 在Flutter的GetX库中,我们可以使用`Obx`方法来实现响应式更新。`Obx`方法接受一个返回`Rx`对象的回调函数作为参数,并在该回调函数中监听数据的变化。在`Obx`回调函数中,我们可以使用`async`和`await`来执行异步操作,以实现更复杂的逻辑。 要在`Obx`方法中使用`async`和`await`,首先定义一个`Rx`对象,例如`RxInt`、`RxString`或`RxList`等,作为需要监听和更新的数据。 接下来,我们可以在`Obx`回调函数中使用`async`关键字来标记该函数为异步函数。然后,可以使用`await`关键字来等待异步操作的结果。 例如,我们可以在`Obx`回调函数中调用一个异步函数,等待其执行完成后更新数据: ``` final count = RxInt(0); void fetchData() async { // 模拟一个耗时的异步操作 await Future.delayed(Duration(seconds: 2)); // 更新count的值 count.value = 10; } Obx(() { return Text('Count: ${count.value}'); }); ``` 在上面的例子中,`count`是一个`RxInt`对象,用来表示需要更新的数据。`fetchData`是一个异步函数,模拟一个耗时的操作,并在操作完成后更新`count`的值。在`Obx`回调函数中,使用`Text`组件显示`count`的值。 当调用`fetchData`函数时,由于其内部包含`await`关键字,程序会等待异步操作完成后再进行下一步的处理。一旦异步操作完成,`count`的值会发生变化,从而触发`Obx`回调函数的执行,更新界面上展示的`Text`组件的内容。 总结来说,在GetX库中,我们可以在`Obx`方法中使用`async`和`await`来执行异步操作,从而实现动态更新界面的效果。 ### 回答3: 在Flutter的GetX库中,Obx方法并不能直接使用async和await关键字。Obx是GetX库中的一个观察者小部件,用于侦听并响应任何被观察对象(例如Rx变量)的更改。但是,可以通过使用RxStream或RxWorker来实现类似于async和await的功能。 要在Obx中实现异步操作,可以使用RxStream。首先,创建一个RxStream对象,并使用StreamController将异步操作包装成一个流。然后,在Obx方法内部,使用Obx(() {})方法来订阅RxStream。每当这个流的数据发生变化时,Obx方法将被调用,可以在其中更新UI。 以下是一个示例代码: ```dart final count = RxInt(0); void incrementCount() async { await Future.delayed(Duration(seconds: 1)); count.value++; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Async Operation')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Obx(() => Text('Count: ${count.value}')), ElevatedButton( child: Text('Increment'), onPressed: incrementCount, ), ], ), ), ); } ``` 在这个示例中,我们使用RxInt来管理一个计数器,名为count。在incrementCount方法中,我们使用async和await关键字模拟了一个异步操作,通过延迟1秒钟来增加计数。在UI中,我们使用Obx(() {})方法订阅了count。每当count发生变化时,Obx内部的匿名函数就会被触发,并在Text小部件中更新显示。 总结来说,尽管Obx方法本身不能直接使用async和await关键字,但可以结合使用RxStream或RxWorker来实现类似的异步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值