对Flutter GetX的一些理解

这篇具有很好参考价值的文章主要介绍了对Flutter GetX的一些理解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

GetX的优势

1.内部实现了路由管理,相比目前主流的fluro框架更轻量,并且路由跳转无需上下文对象,支持自定义路由中间件和动态路由传参等功能。
2.提供两种简单灵活的实现状态管理的方式。
3.它内部实现了依赖注入,可以快速的获取到某个状态管理器(GetxController)。
4.在实际开发中,通过上述三点配合使用,可以将界面、业务、路由、依赖等进行分离。在做到UI刷新跨界面交互的同时,又能提高整体模块代码的可维护性和架构的可扩展性
5.提供修改全局语言/主题和其他的一些高级Api以及GetUtils工具类等。
6.可以全局获取上下文对象,所以上述场景都是不需要Context的。
7.只有用到的模块才会被编译到代码中,不会导致包体积增大
8…

状态管理

常用的几种状态管理对比

1.Bloc非常安全和高效,但是模版代码太多,实现太过复杂。
2.Provider内部使用InheritedWidget且依赖上下文对象,对其ChangeNotifier类的任何访问都必须在widget树或widget子树内。
3.Fish_redux层次划分是比较细的,但是写起来很费劲,每次都要生成很多文件。
4.那其实每种方式都有其优缺点,但是Get并不是比任何其他状态管理更好,而是通过和它提供的其他模块搭配使用,使得模块代码更简单灵活且易维护而已。

GetxController *

1.主要是用于分离UI代码与业务逻辑2.提供可以手动刷新UI的方法(update())3.提供和StatefulWidget类似的生命周期,常用的有以下这三个方法1.onInit:数据初始化、加载缓存等处理2.onReady:界面渲染第一帧后调用,刷新UI的操作需要在这里处理3.onClose:做一些清除资源等处理

Get提供响应式状态简单状态两种状态管理器

响应式状态管理器

主要通过Obx和GetX Widget实现,但是GetX Widget 会多消耗内存,所以只介绍Obx的使用

1.创建控制器并继承GetxController,通过.obs扩展方法声明响应式变量(Rx)class Controller extends GetxController { var count = 0.obs}​extension DoubleExtension on double {  RxDouble get obs => RxDouble(this);} 2.使用Obx方法实现定点刷新final logic = Get.find<Controller>();Obx(() => Text(  '${logic.count.value}',));​ 3.Obx()方法刷新的条件* 只有当响应式变量的值发生变化时,才会执行刷新操作,当某个变量初始值为:0,再赋值为:0,并不会执行刷新操作* 该响应式变量改变时,只有包裹该响应式变量的Obx()方法才会执行刷新操作(局部刷新)

简单状态管理器GetBuilder

1.创建控制器并继承GetxControllerclass Controller extends GetxController {  int counter = 0;  void increment() {    counter++;    update();}} 2.通过GetBuilder包裹想要刷新的UI// Stateless/StatefulGetBuilder<Controller>(  // 未注入的控制器需要进行初始化  init: Controller(),  builder: (_) => Text(    '${_.counter}',),) 3.当多处引用了同一个属性,但只想单独更新某一个地方,那么就可以用UniqueID来进行区分。class Controller extends GetxController {  int counter = 0;  void increment() {    counter++;    update(['hc_count']);}}​GetBuilder<CountController>(    builder: (controller) {  return Text(      "${controller.counter}",      style: TextStyle(color: Colors.red, fontSize: 30),    );  },),​GetBuilder<CountController>(    id: 'hc_count',    builder: (controller) {      return Text(      "${controller.counter}",      style: TextStyle(color: Colors.green, fontSize: 30),    );  },), 但是一般这种场景很少见,不需要刷新的直接通过find Controller拿数据就可以。不需要用GetBuilder包裹。或者说有应用其他场景,暂时没想到#### 总结

1.Obx是配合响应式变量使用;GetBuilder是配合update使用。前者响应式变量变化,Obx自动刷新;后者需要使用update手动调用刷新。
2.每一个响应式变量,都会生成对应的GetStream,会对内存造成一定压力。
3.但GetBuilder内部实际上是对StatefulWidget的封装,所以占用资源极小。
4.一般来说,对于大多数场景都是可以使用响应式变量的。但是,在一个包含了大量对象的List,都使用响应式变量的话,将会生成大量的GetStream,会对内存造成较大的压力。该情况下,就要考虑使用简单状态管理了。
5.所以更推荐GetBuilder和update配合的方式,并且GetBuilder内置回收GetxController的功能。

依赖注入

依赖注入简单来说就是将一个类的实例注入另一个类,主要是为了将依赖组件的配置和使用分离开,降低使用者与依赖之间的耦合度。

Flutter中注入依赖项的基本方法是通过构造函数

class XXXWidget extends StatelessWidget {
​
  Controller controller; 
​
  XXXWidget({this.controller}); 
}
​
class XXX1Widget extends StatelessWidget {
​
  Controller1 controller; 
​
  XXX1Widget({this.controller}); 
}
​
class OtherPage extends StatelessWidget {
  
  Controller someController = Controller();
  
  Controller1 someController1 = Controller1();
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
         XXXWidget(controller: someController),
         XXX1Widget(controller: someController1),
    ],
  );}
} 

可以看到这里还是存在一定的耦合。

那Get为了解决这种依赖的问题,提供了一个简单而强大的依赖管理器,只用1行代码就能检索到 Controller 或者需要依赖的类,不需要提供上下文,不需要在 inheritedWidget 的子节点

包含两种注入:立即注入懒注入

内部实现:

1.将继承自GetxController的类的实例引用添加到内部的全局Map对象里
2.立即注入会在添加成功后主动调用find方法创建实例,可以直接使用
3.懒注入会在手动调用Get.find方法后,才可以使用
4.只有每次调用Get.find之后,才会真正创建实例。

立即注入
final logic = Get.put<LoginController>(); 
懒注入
Get.lazyPut(() => LoginController());
​
Get.find<LoginController>();
​
Get.lazyPut<S>(
  // 必须:当你的类第一次被调用时,将被执行的方法。
  InstanceBuilderCallback builder,
  
  // 可选:和Get.put()一样,当你想让同一个类有多个不同的实例时,就会用到它。
  // 必须是唯一的
  String tag,
​
  // 可选:下次使用时是否重建,
  // 当不使用时,实例会被丢弃,但当再次需要使用时,Get会重新创建实例,
  // 就像 bindings api 中的 "SmartManagement.keepFactory "一样。
  // 默认值为false
  bool fenix = false
  
)
​ 

当加载了无数条路由,现在需要拿到一个被遗留在某一个控制器中的数据,就不需要任何额外的依赖关系。只需要通过Get.find()就可以拿到对应的控制器数据,同样可以通过此方式实现跨界面交互。

Bindings

上面实现了依赖注入和使用,但是和前面讲的手动注入一样。都需要在 Widget 里注入,并没有完全解耦。那这个时候就可以通过Binding自动注入的方式去进行解耦

1.在路由跳转页面加载时注入当前页面所需的依赖关系。
2.可以将路由、状态管理器和依赖管理器完全集成。
3.当一个路由移除时,所有与它相关的控制器、变量和对象的实例都会从内存中移除。
4.同时Get可以通过它很清楚的知道当使用某个控制器时,哪个页面正在显示,并知道在哪里以及如何销毁它

使用

1.创建控制器以及继承自Bindings的类,重写dependencies方法进行懒注入控制器class MainLogic extends GetxController {}class MainBinding extends Bindings {@overridevoid dependencies() {Get.lazyPut(() => MainLogic());}} 2.使用该 Binding 来建立路由管理器、依赖关系和状态之间的连接。使用命名路由GetPage(name: RouteConfig.mainPage,page: () => const MainPage(), binding: MainBinding()// bindings: [MainBinding()],), 3.使用// 需刷新的UI,在界面无需手动注入以及指定init GetBuilder<HomeLogic>(builder: (logic) {// }),// 获取控制器数据final logic = Get.find<MainLogic>();logic.xxx 路由管理

分为普通路由命名路由

上面提到的路由+状态管理+依赖注入配合使用,是需要通过命名路由的方式去实现配置。所以强烈推荐使用命名路由的方式,尤其是使用自动注入的时候。因此重点讲一下命名路由

配置

1.声明别名+注册路由表class RouteConfig {static String mainPage = '/mainPage';static final List<GetPage> getPages = [ GetPage(name: '/',page: () => UserLogic.hasAgreeProtocol()? UserLogic.userInfo != null? const MainPage(): LoginPage(): const ProtocolDialogPage(),bindings: [if (UserLogic.userInfo != null) UserBinding(),MainBinding(),HomeBinding(),if (UserLogic.userInfo == null) LoginBinding(),GetCodeBinding()]),GetPage(name: mainPage,page: () => const MainPage(),bindings: [UserBinding(), MainBinding(), HomeBinding()],transition: Transition.fadeIn),];} 2.替换MaterialApp为GetMaterialApp,指定getPagesGetMaterialApp(getPages: RouteConfig.getPages,// initialRoute: RouteConfig.xxx,// unknownRoute: RouteConfig.xxx,)); 3.如果没有配置根路由,还需要指定initialRoute4.支持配置未知路由,避免跳转黑屏#### 跳转

无需Context。所以就可以在分离出的业务逻辑里执行跳转,而无需再维护一个和业务相关的UI界面的Context

1.跳转到下个界面

Get.toNamed(RouteConfig.mainPage); 

2.跳转下一个界面并清除当前界面

Get.offNamed(RouteConfig.mainPage); 

3.跳转下一个界面并清除之前所有界面

Get.offAllNamed(RouteConfig.mainPage); 

4.返回上个界面

Get.back();
// 回传参数d
Get.back(result: T); 
传递数据

只要发送你想要的参数即可。无论是一个字符串,一个Map,一个List,甚至一个类的实例。

Get.toNamed(RouteConfig.mainPage, arguments: 'Get is the best'); 

在你的类或控制器上:

Get.arguments 
动态路由传参
Get.toNamed(RouteConfig.mainPage+'?id=xxx&name=xxx'); 

在你的类或控制器上:

Get.parameters['id'] 

使用场景Ex:H5携带参数跳转App界面、后端返回路由的地址进行跳转等

web端会在地址栏显示这个url

重复跳转

路由内部处理了多次点击重复跳转的问题,可以通过preventDuplicates解除此限制

Get.toNamed(RouteConfig.mainPage, preventDuplicates: false); 
获取前一个路由

使用场景Ex:埋点前向地址(仅针对静态地址,动态地址还是要通过路由传值或者获取控制器数据进行处理)

String previousRoute = Get.previousRoute;
if (previousRoute.contains(RouteConfig.evalDetailPage)) {
	referrer = '测评组详情';
} else if (previousRoute.contains(RouteConfig.myEvalPage)) {
	referrer = '我的测评列表';
} 
调用部分内置组件无需Context

无需Context即可调用Flutter提供的的Snackbar、Dialog、BottomSheet

1.SnackbarGet.snackbar('Hi', 'i am a modern snackbar');// 检查 snackbar 是否打开Get.isSnackbarOpen 2.DialogGet.dialog(YourDialogWidget());Get.defaultDialog(onConfirm: () => print("Ok"),middleText: "Dialog made in 3 lines of code");// 检查 dialog 是否打开Get.isDialogOpen 3.BottomSheetGet.bottomSheet(Container(child: //));// 检查 bottomsheet 是否打开Get.isBottomSheetOpen 4.同样是使用Get.back()关闭#### 路由GetPage中间件

它是在跳转某一个界面前做一些操作,比如:路由鉴权,判断登录状态、游客模式、青少年模式、部分界面权限处理等等

1.声明中间件1.继承GetMiddleware2.重写priority变量指定优先级,优先级越低越先执行3.一般只需要重写redirect和onBindingsStart这两个方法;如果需要修改重定向路由的一些参数(跳转动画等),就需要重写onPageCalled方法4.redirect指定当前重定向的路由5.onBindingsStart:这个函数将在绑定初始化之前被调用, 可以更改此页面的绑定。(4.6.1版本上方法不执行)import 'package:flutter/widgets.dart';import 'package:happy_cece/common/logic/user/user_logic.dart';import 'package:happy_cece/config/route/binding.dart';import 'package:happy_cece/index.dart';/// 登录状态中间件class RouteLoginMiddleWare extends GetMiddleware {final int priorityT;RouteLoginMiddleWare({this.priorityT = 0});@overrideint? get priority => priorityT;@overrideRouteSettings? redirect(String? route) {return ObjectUtil.isNotEmpty(UserLogic.userInfo?.apiToken)? null: const RouteSettings(name: RouteConfig.loginPage);}@overrideList<Bindings>? onBindingsStart(List<Bindings>? bindings) {bindings ??= [];return bindings..add(LoginBinding())..add(GetCodeBinding());}} onPageCalled在调用页面时,这个函数会先被调用。 可以使用它来更改页面的某些内容或给它一个新页面。应用场景:修改重定向的路由的一些配置:跳转动画,Bindings等。这种情况下redirect就不需要重写了,不然onPageCalled就会失效import 'package:flutter/widgets.dart';import 'package:happy_cece/common/logic/user/user_logic.dart';import 'package:happy_cece/index.dart';import 'package:happy_cece/page/login/view/login.dart';import '../binding.dart';/// 游客模式状态中间件class RouteTouristMiddleWare extends GetMiddleware {final int priorityT;RouteTouristMiddleWare({this.priorityT = -1});@overrideint? get priority => priorityT;// @override// RouteSettings? redirect(String? route) {// bool tourist = Constant.tourist;// if (tourist) {// showToast('当前是游客模式,请先登录');// }// return !tourist ? null : const RouteSettings(name: RouteConfig.loginPage);// }@overrideGetPage? onPageCalled(GetPage? page) {if (Constant.tourist) {showToast('当前是游客模式,请先登录');return GetPage(name: RouteConfig.loginPage,page: () => LoginPage(),bindings: [LoginBinding(), GetCodeBinding()],transition: Transition.downToUp);}return page;}} 其它方法基本用不到:OnPageBuildStart这个函数将在绑定初始化之后被调用。 在这里,您可以在创建绑定之后和创建页面widget之前执行一些操作。GetPageBuilder onPageBuildStart(GetPageBuilder page) {print('bindings are ready');return page;} OnPageBuilt这个函数将在GetPage.page调用后被调用,并给出函数的结果,并获取将要显示的widget。OnPageDispose这个函数将在处理完页面的所有相关对象(Controllers, views, …)之后被调用。2.在GetPage里注册GetPage(name: RouteConfig.mainPage,page: () => const MainPage(),bindings: [UserBinding(), MainBinding(), HomeBinding()],middlewares: [RouteProtocolMiddleWare(), RouteLoginMiddleWare()],transition: Transition.fadeIn,), 3.这个时候GetMaterialApp就可以指定mainPage为根路由,然后通过中间件的方式,就可以实现未同意协议去协议界面,未登录去登录界面的逻辑。相比上面提到的配置根路由的方式更优雅,且可以在多个界面绑定处理GetMaterialApp(initialRoute: RouteConfig.mainPage,getPages: RoutePaths.getPages,) 分析如何使用GetX更好的组织项目架构和模块代码

通过命名路由的方式配置项目路由模块

1.配置路由名称
2.配置路由注册表
3.配置路由中间件和路由进行绑定
4.配置Bindings自动注入和路由进行绑定
5.替换为GetMaterialApp,并配置初始化路由

通过GetX插件快速生成模块代码

[[GetX代码生成插件] ]  github.com/xdd666t/get…

一般会生成4个文件

1.logic/controller:业务逻辑层
2.state:状态层。在业务不复杂的情况下,可以直接放在业务逻辑层
3.view:UI层
4.Bindings:自动注入层,一般不会修改此文件,所以可以放到路由管理的那个Binding公共类

目的:将业务逻辑、状态、UI等进行解耦

配置全局状态管理器

如:通用验证码获取控制器、图片上传进度控制器、用户信息控制器、主程序控制器、全局语言/主题控制器等,并在适当的时候进行注入

业务模块配置

1.通过实际业务场景分析每个模块间的关联性,然后将通用,共用的业务逻辑代码或UI代码进行分离和封装到Controller逻辑层中。2.模块间跨界面交互* UI交互* 业务逻辑交互* 获取值

其他配置

1.公共组件
2.工具类
3.网络请求
的那个Binding公共类

目的:将业务逻辑、状态、UI等进行解耦

配置全局状态管理器

如:通用验证码获取控制器、图片上传进度控制器、用户信息控制器、主程序控制器、全局语言/主题控制器等,并在适当的时候进行注入

业务模块配置

1.通过实际业务场景分析每个模块间的关联性,然后将通用,共用的业务逻辑代码或UI代码进行分离和封装到Controller逻辑层中。2.模块间跨界面交互* UI交互* 业务逻辑交互* 获取值

其他配置

1.公共组件
2.工具类
3.网络请求
4…文章来源地址https://www.toymoban.com/news/detail-401983.html

到了这里,关于对Flutter GetX的一些理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Flutter 全能型选手GetX —— 状态管理

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

    2024年02月02日
    浏览(48)
  • Flutter GetX 实现 ChatGPT 简单聊天界面

    Flutter 是一款跨平台的移动应用开发框架,而 GetX 是 Flutter 中一种简单易用的状态管理和路由管理工具。本篇我们将使用 Flutter 和 GetX 实现一个简单的聊天界面,以与 ChatGPT 进行交互。 我们需要在 Flutter 项目中引入 GetX 库。在 pubspec.yaml 文件中添加以下依赖: 在 main 函数中添

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

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

    2024年02月05日
    浏览(42)
  • Flutter GetX使用

    下载地址: https://pub-web.flutter-io.cn/packages/get 导入依赖: 导入头文件: 创建全局数据 Counter ,继承 GetxController : 添加依赖: 添加组件 Obx() ,监听显示数据: 改变数据: 创建全局数据 MyController 继承 GetxController : 添加依赖: 添加组件 GetBuilderT : 在添加的依赖是全局的,考

    2024年02月16日
    浏览(36)
  • Flutter GetX的使用

    比较强大的状态管理框架 引入库: 实现一个计数器功能 代码如下: 1.状态管理 Get 有两种不同的状态管理器:简单状态管理器(我们称之为 GetBuilder)和反应式状态管理器(GetX/Obx) 使用 Get 进行响应式编程与使用 setState 一样简单。 要使其可观察,您只需在其末尾添加“.

    2024年02月05日
    浏览(42)
  • Flutter GetX使用详解

    GetX是一款功能强大且轻量级的Flutter状态管理和路由管理库。它提供了一种简单而强大的方式来构建Flutter应用程序,无需大量的模板代码。GetX不仅提供了状态管理和路由管理,还包括其他实用工具,如国际化和依赖注入。 在本文中,我们将深入探讨GetX的核心功能,并通过实

    2024年02月08日
    浏览(38)
  • flutter getx 简单使用教程

    所以Flutter使用GetX真的很不错 为什么说什么GetX好用呢? 1、依赖注入 GetX是通过依赖注入的方式,存储相应的XxxGetxController;已经脱离了InheritedWidget那一套玩法,自己手动去管理这些实例,使用场景被大大拓展 2、跨页面交互 这绝对是GetX的一个优点!对于复杂的生产环境,跨

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

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

    2024年01月19日
    浏览(62)
  • Flutter GetX页面跳转动画与属性

    Flutter GetX页面跳转动画解释: fade: 页面渐变动画,新页面会从透明度为 0 的状态渐变到完全显示。 fadeIn: 渐入动画,新页面会从透明度为 0 的状态渐变到完全显示。 rightToLeft: 从右向左滑动动画,新页面从屏幕右侧滑入显示。 leftToRight: 从左向右滑动动画,新页面从屏幕左侧

    2024年02月06日
    浏览(49)
  • 关于路由器和DNS解析的一些新理解

    其实我本人对于交换机和路由器这些网络硬件是比较感兴趣的,也在一点一点的学习相关知识,每次解决一个问题,就让我对一些事情有新的思考。。 今天前台同事,的机器突然上不了网,,和领导一起去看了一波,首先ping了一下网关,,然后发现,可以ping通的,然后pin

    2024年02月12日
    浏览(50)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包