Flutter笔记:GetX模块中不使用 Get.put 怎么办

这篇具有很好参考价值的文章主要介绍了Flutter笔记:GetX模块中不使用 Get.put 怎么办。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Flutter笔记
GetX模块中不使用 Get.put 怎么办

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134006728



1. 概述

2. 关于依赖注入

依赖注入(Dependency Injection,DI)是一种编程模式,它旨在管理和注入类之间的依赖关系,以提高代码的可维护性、可测试性和可扩展性。

在 Dart 语言中,依赖注入可以通过不同的方式实现。下面大概看一下一些常见的实现依赖注入的方式。

1. 手写依赖注入

手写依赖注入的有以下三个步骤:

  1. 创建依赖项类:首先创建依赖项的类,这些类包括服务、存储库或其他应用程序组件。
  2. 创建依赖关系:在应用程序中创建依赖项之间的关系,这可以通过构造函数参数或依赖项属性来实现。
  3. 注入依赖项:将依赖项注入到需要它们的类中,通常在构造函数中进行注入。

比如:

// 步骤 1:创建依赖项类
class DataService {
  String fetchData() {
    return "Data from DataService";
  }
}

class Logger {
  void log(String message) {
    print(message);
  }
}

class MyService {
  final DataService dataService;
  final Logger logger;

  // 步骤 2:创建依赖关系
  MyService(this.dataService, this.logger);

  void doSomething() {
    String data = dataService.fetchData();
    logger.log(data);
  }
}

void main() {
  // 步骤 3:注入依赖项
  final dataService = DataService();
  final logger = Logger();
  final myService = MyService(dataService, logger);

  myService.doSomething();
}

这个例子中,MyService 类依赖于 DataServiceLogger 类,这两个依赖项被通过构造函数注入到 MyService 中。对于大型应用程序,可能需要考虑使用依赖注入容器或注解处理器来更方便地管理依赖项。下面两个小节继续介绍。

2. 使用依赖注入容器

依赖注入容器是管理和注入依赖项的工具,它们可以简化依赖管理过程并提供更高级的功能。在 Dart 中,一些流行的依赖注入容器包括 get_itinjectorkiwi 等。

使用 get_it 的示例:
import 'package:get_it/get_it.dart';

class DataService {
  String fetchData() {
    return "Data from DataService";
  }
}

class MyService {
  final DataService dataService;

  MyService(this.dataService);

  void doSomething() {
    String data = dataService.fetchData();
    print(data);
  }
}

void main() {
  final getIt = GetIt.instance;
  getIt.registerSingleton<DataService>(DataService());
  getIt.registerFactory<MyService>(() => MyService(getIt<DataService>()));
  
  final myService = getIt<MyService>();
  myService.doSomething();
}

在上述示例中,使用 get_it 容器注册并获取依赖项。 get_it 允许您注册单例和工厂方法来创建依赖项,并且能够在整个应用程序中轻松访问这些依赖项。

3. 注解处理器和代码生成

另一种方式是使用注解处理器和代码生成工具,如 injectget_it 的 Generator,来自动生成依赖注入代码。这些工具可以根据您的类和注解自动生成依赖注入的代码,减少手动编写依赖注入的工作。

// 使用 inject 注解
import 'package:inject/inject.dart';


class MyModule {
  
  DataService provideDataService() => DataService();
}

class DataService {
  String fetchData() {
    return "Data from DataService";
  }
}

class MyService {
  final DataService dataService;

  MyService(this.dataService);

  void doSomething() {
    String data = dataService.fetchData();
    print(data);
  }
}

void main() {
  final injector = Injector<MyModule>().injector;
  final myService = injector.get<MyService>();
  myService.doSomething();
}

在上述示例中,使用了 inject 注解处理器来生成依赖注入代码,简化了依赖项的注册和获取。

无论您选择手动注入、依赖注入容器还是注解处理器,依赖注入都有助于将应用程序的组件解耦,提高代码的可测试性和可维护性。这种模式在构建大型、复杂的应用程序时特别有用,使代码更易于扩展和维护。

3. 什么是 Get.put

Get.put 是 GetX 状态管理库中的一个方法,它用于将一个控制器(Controller)实例放入 GetX 的依赖注入容器中,使得该控制器可以在整个应用程序中被共享和访问。

  1. 获取依赖: Get.put 的主要目的是将一个控制器实例添加到 GetX 的依赖注入系统中。这可以让您的控制器在整个应用程序中被轻松访问和共享。

  2. 依赖注入: GetX 使用依赖注入来管理应用程序的状态。依赖注入是一种设计模式,它有助于管理对象之间的依赖关系。在这种情况下,Get.put 用于将一个控制器添加到应用程序的依赖项容器中,以便其他部分可以访问它。

  3. 单例模式: 默认情况下,Get.put 创建的控制器是单例的。这意味着无论应用程序的哪个部分使用 Get.find 或其他方法获取该控制器,都将获得同一个实例。这对于共享应用程序状态和逻辑非常有用。

使用示例:

class MyController extends GetxController {
  var count = 0.obs;
}

// 在应用程序的某个地方将 MyController 放入依赖注入容器中
Get.put(MyController());

// 在其他部分可以轻松获取 MyController 实例
MyController myController = Get.find<MyController>();

// 使用 MyController 实例
myController.count.value = 42;

总之,Get.put 允许您在整个应用程序中访问和共享控制器,是 GetX 库的关键部分,用于实现轻量级的状态管理和依赖注入。

4. 有时候我还真的不喜欢过多使用Get.put

从简单状态管理说起

GetX 模块中提供了太多的解决方案,其中甚至包括 StatefulWidget 的替代方案。GetX 模块官方文档中就直接说,通过 简单状态管理, 你 不再需要 StatefulWidget。比如,经典的几乎在每一个响应式框架都喜欢给出的计数器例子:

// your/path/count_controller.dart

class Controller extends GetxController {
  int counter = 0;
  void increment() {
    counter++;
    update(); // 当调用增量时,使用update()来更新用户界面上的计数器变量。
  }
}
import 'your/path/count_controller.dart'

// ...其它代码

GetBuilder<Controller>(
  init: Controller(), // 首次启动
  builder: (_) => Text(
    '${_.counter}',
  ),
)

这个例子中,使用的就是GetX提供的所谓 简单状态管理 的方式。它的状态保存在 Controller 类中,然后在需要用到的地方使 GetBuilder进行包装。

Get.put 和 Get.find

但是——考虑下面一个问题:

你此定义的 Controller 是一个全局状态,它可能不是在一个类、甚至一个文件中的代码中需要使用。那么,你会每次都创建 Controller 类的实例吗?显然这就不能共享数据状态了。

怎么办呢?对于全局共享的数据,很多情况下我们都是使用 Get.putGet.find 来实现的,它们是 GetX 框架提供了一种方便的方式来管理应用程序状态和访问依赖项。

Get.put函数

Get.put 函数用于将一个对象注册为单例,以便在整个应用程序中重用。它通常用于注册 控制器、服务、数据存储类 等全局性的依赖项,使它们可以在整个应用程序的生命周期内被访问。

使用Get.put时,您需要提供一个对象的实例。通常,这将是一个控制器类的实例。比如,下面的例子展示了如何在GetX中使用Get.put来注册和访问一个控制器:

// 1. 创建一个控制器类
class MyController extends GetxController {
  // 控制器的逻辑和状态
}

// 2. 在应用程序初始化时使用Get.put注册控制器
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    // 注册MyController控制器为单例
    Get.put(MyController());

    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // 3. 在应用程序的任何地方使用Get.find获取控制器实例
              final myController = Get.find<MyController>();
              // 使用myController来访问控制器的逻辑和状态
            },
            child: Text('Get Controller'),
          ),
        ),
      ),
    );
  }
}

Get.find函数

`Get.find 函数用于查找和获取已经注册的单例对象(通常是控制器)的实例。它用于在应用程序的任何地方访问注册的对象,而无需手动传递它们。

使用Get.find时,需要提供对象的类型,以获取已注册对象的实例。可以在应用程序的任何部分使用Get.find来获取已注册对象的实例,而无需显式传递它们。例如

// 获取已注册的MyController对象实例
final myController = Get.find<MyController>();

// 使用myController来访问控制器的逻辑和状态

使用 GetxController.find创建单例

依据GetX官方的介绍,如果你需要在许多其他地方使用你的控制器,并且在GetBuilder之外,只需在你的控制器中创建一个get,就可以轻松地拥有它。(或者使用Get.find()) 例如:

class Controller extends GetxController {

  /// 你不需要这个,我推荐使用它只是为了方便语法。
  /// 用静态方法:Controller.to.increment()。
  /// 没有静态方法的情况下:Get.find<Controller>().increment();
  /// 使用这两种语法在性能上没有区别,也没有任何副作用。一个不需要类型,另一个IDE会自动完成。
  static Controller get to => Get.find(); // 添加这一行

  int counter = 0;
  void increment() {
    counter++;
    update();
  }
}

于是,你可以直接访问你的控制器:

FloatingActionButton(
  onPressed: () {
    Controller.to.increment(),
  } 
  child: Text("${Controller.to.counter}"),
),

哦,看起来似乎“贼简单”,不过接下来就是报错:

错误信息提示你,你需要先使用 Get.put 添加作为依赖添加给GetX框架管理。

—— 对的,我们使用的依然是 Get.find(),还需要见Get.put(); 一下。于是你很不情愿地又在 mian 的一大堆代码中添加了一个导入,创建了一个新的控制器实例,并添加了一条依赖注入。

替代StatefulWidget

既然简单状态管理在很多场景下用于替代StatelessWidget,而一旦遇到想考虑拆分组件避免一个组件写的过大时,就可能遇到简单状态需要在多个拆分后的组件中局部进行共享的问题。

由于,毕竟从需求上来说,这些状态还真的没有其它需要用到的地方了,如果都像 GetService一样去注册,写在 GetMaterialApp 中注册的就会特别多。

一般为了方便查找,我考虑写一个 app/injections.dart 文件,同意管理依赖注入项目,比如:

import 'package:get/get.dart';

import '../xxx.dart';


class DependencyInjection {
  static void init() {
    Get.put<GetConnect>(GetConnect());
    Get.put<GetProvider>(GetProvider());
    Get.put<GetProvider>(GetProvider());

    Get.put(AuthService(GetProvider()));

    Get.put(RecommendationController());
    Get.put(CartController());
  }
}

而在 mian.dart 的应用组件中(如“Myapp”),可以实现一个初始化方法,在这里和其它需要初始化的项目一起完成依赖初始化:

class Myapp extends StatelessWidget {
  const Myapp({super.key});

  Future<void> initialization(BuildContext context) async {
    // ... 其它需要初始化的内容
    DependencyInjection.init(); // 初始化依赖注入
  }
}

虽然这已经可以使得代码显得更加整洁清晰。但是,对于一些真的仅仅就是部分代码中共享的状态,我还是不想在 app/injections.dart 注册,我希望仅仅在这些代码中调用的地方才创建实例而不是在应用一启动就有GetX管理单例。

不仅是减少没必要的实例创建,同时我页不用大范围的找文件,尤其是项目变大的时候。那么如果不依赖注入,还有什么办法呢。请看下节。

5. 手动使用单例

简介

这个办法就是在控制器类上做一些手脚,保证外部访问的都是同一实例——实际上使用GetX的Get.put方法时,内部管理的也不就是我们注册的单例。

对于很多真的就是简单的局部共享状态的场景,自己实现单例我个人感觉反而更好。首先,你不需要集中于创建代码初期就从各个模块中导入你的各个控制器,也不需要预先在应用初始化时就创建它们的实例,从而将实例添加到GetX依赖中进行管理。这使得mian文件中的代码更加简洁。如果某个局部状态控制器被移除,你也不需要回到mian文件中来对代码进行改动,只需要删除不用的部分。其次,在Dart语言中,为面向对象的单例实现提供了很方便的支持,仅仅三个小步骤就可以实现严格管理单例。接下来就我们看一下具体该怎么搞。

实现过程

为控制器实现单例可以按照下面的三个步骤进行:

  1. 供一个私有静态属性用于存储唯一的控制器实例;
  2. 创建用于内部静态构造的构造器,尽量避免提供外部可访问的构造方法;
  3. 提供一个外部访问的访问器接口,在该接口中:
  • 如果还没有创建过控制器,则内部构建数以该类的唯一构造器实例后返回;
  • 如果存储的构造器已经非空,则返回该之前创建过的属于该类的唯一构造器实例。

具体案例

基于以上步骤,一个计数器控制器增加单例控制的面向对象实现如下:

import 'package:get/get.dart';

/// 计数器控制器类
class CounterController extends GetxController {
  // 提供一个私有静态属性用于存储唯一的控制器实例
  static CounterController? _instance;

  // 仅提供一个私有构造器防止外部创建实例
  CounterController._();

  // 提供一个外部访问的访问器接口
  static CounterController? get to {
    // 表示仅仅当 _instance 为 null 时,内部构造该控制器实例
    _instance ??= CounterController._();
    return _instance;
  }

  // 下面表示一些状态变量个状态相关的内容...
  int counter = 0;
  void increment() {
    counter++;
    update();
  }
}

接着,就可以在完全不通过 Get.put函数和Get.get函数情况下,改用 CounterController.to 访问器直接使用单例了。文章来源地址https://www.toymoban.com/news/detail-719740.html

到了这里,关于Flutter笔记:GetX模块中不使用 Get.put 怎么办的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • flutter使用getx进行数据状态管理,实现页面响应式

    无论是什么样的应用,都还是需要最基础的数据来支撑的,而且不同的页面之间可能需要共享数据状态,这就显得数据状态管理非常有必要了。因为我这里使用了get依赖库,所以就可以直接在项目中使用getx来管理状态,不想再使用别的框架了。而且getx使用起来也挺方便的。

    2024年01月22日
    浏览(34)
  • Flutter中GetX系列六--GetxController/GetView使用详情

    在实际的项目开发过程中,我们不可能把UI代码、业务逻辑都放在一起处理,这样对项目的架构、代码的可读性、后期的维护将会是致命的,好在 GetX 为我们提供了 GetxController , GetxController 主要的作用是用于UI代码与业务逻辑分离开来。 这里主要讲解使用 GetxController 动态获取

    2024年02月10日
    浏览(38)
  • https请求httputil方法的使用实例get,post,put

    一、get方式 返回数据格式 这里可以用类来接收,然后获取data里面数据(如上) 二、post方式 三、put方式

    2023年04月09日
    浏览(72)
  • 【LibCurl】C++使用libcurl实现HTTP POST和GET、PUT

    libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证 libcurl的官网: http://curl.haxx.se/ 库下载地址: https://github.com/curl/curl/releases/tag/curl-7_71_1 初

    2024年04月17日
    浏览(70)
  • 【Flutter】Flutter GetX 传递参数

    在 Flutter 开发中,状态管理和数据传递是两个非常重要的环节。今天,我们将介绍一个强大的库——GetX,它可以帮助我们更高效地进行状态管理和数据传递。本文的重点包括: 了解 GetX 是什么以及它的主要功能 学习如何在 Flutter 中安装和使用 GetX 掌握如何使用 GetX 进行参数

    2024年02月05日
    浏览(31)
  • Flutter GetX 之 国际化

    今天给大家介绍一下 GetX 的国际化功能,在日常开发过程中,我们经常会使用到国际化功能,需要们的应用支持 国际化,例如我们需要支持 简体、繁体、英文等等。 上几篇文章介绍了GetX的 路由管理 和 状态管理,看到大家的点赞和收藏,还是很开心的,说明这两篇文章给大

    2024年01月19日
    浏览(50)
  • Flutter 状态管理之GetX库

      Flutter使用的是声明式UI,是通过状态去更新UI组件的,因此我们首先就要学习状态的使用。同样为了简化原本的状态使用,我们会使用Getx库。   之前说要写Flutter,一拖就是一年多,有些不好意思。现在都24年了,终于等到你,下面还是按照我们最属于的思路来吧。 首

    2024年01月23日
    浏览(30)
  • 对Flutter GetX的一些理解

    1.内部实现了 路由管理 ,相比目前主流的fluro框架更轻量,并且路由跳转无需上下文对象,支持自定义路由中间件和动态路由传参等功能。 2.提供两种简单灵活的实现状态管理的方式。 3.它内部实现了依赖注入,可以快速的获取到某个状态管理器( GetxController )。 4.在实际开发

    2023年04月08日
    浏览(23)
  • Flutter 全能型选手GetX —— 状态管理

    使用篇 简介 依赖管理 路由管理 状态管理 主题配置 多语言配置 离线缓存 网络请求 原理篇 Flutter 从源码看Getx的依赖原理 Obx:响应式状态管理,当数据源变化时,将自动执行刷新组件的方法 GetX:响应式状态管理,当数据源变化时,将自动执行刷新组件的方法 GetBuilder:简单

    2024年02月02日
    浏览(34)
  • flutter getx nested navigation 嵌套路由

    https://youtu.be/SXER4JVBFps 嵌套路由可以用在如购物确认向导界面切换。 使用 getx 实现嵌套路由,需要如下步骤: 通过 Navigator 组件的 key 属性 用 Get.nestedKey(1) 进行标记 onGenerateRoute 决定去哪个视图界面 initialRoute 初始路由 通过 Get.toNamed 的 id 属性执行嵌套路由 第一步:准备工作

    2024年02月11日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包