Flutter中GetX的用法(超详细使用指南之路由依赖管理篇)

目录

1.前言

2.GetX 依赖管理概述

1.GetX 依赖管理的基本概念

2.与其他依赖管理工具的比较

3. 基础依赖注入

1.Get.put

2.Get.lazyPut

3.Get.putAsync

4.高级依赖注入

1.使用Get.create

2.依赖生命周期管理

5. 参考资料


1.前言

        今天这篇博客主要介绍Getx的三大功能之一的依赖管理。依赖管理是软件开发中的一个关键部分,尤其是在复杂应用中。它帮助开发者管理应用中的各种依赖,确保依赖的实例化和生命周期管理变得更加简单和高效。

2.GetX 依赖管理概述

1.GetX 依赖管理的基本概念

        GetX 提供了一种简单且高效的依赖注入方式,通过少量代码即可实现依赖的注入、管理和访问。它主要通过Get.put、Get.lazyPut、Get.putAsync和Get.create等方法来实现依赖管理。

2.与其他依赖管理工具的比较

        Provider:Provider 是 Flutter 官方推荐的依赖注入和状态管理工具。它需要较多的样板代码,使用起来相对复杂。
        Riverpod:Riverpod 是 Provider 的增强版,提供了更多的功能和更好的性能,但学习曲线较陡。
        GetX:GetX 简单易用,提供了更多的功能,如路由管理和状态管理,适合各种规模的项目。

3. 基础依赖注入

1.Get.put

        Get.put 是 GetX 提供的一个方法,用于将一个实例注入到依赖管理系统中。它的主要作用是创建一个新的实例,并将其注册为依赖,供整个应用程序的其他部分使用。使用 Get.put 可以方便地管理和访问依赖实例,避免手动管理实例的生命周期。

        它的使用场景如下:

        1.全局单例:需要在整个应用程序中共享的依赖。

        2.初始化即创建:需要在应用启动时立即创建的依赖。

        我们使用Get.put的时候,还可以配置一些选项:

  1. dependency:要注入的依赖实例
  2. tag:依赖实例的可选标签,用于区分相同类型的不同实例。
  3. permanent:是否将依赖设置为永久存在,即使不再使用也不会被销毁。

       我们可以通过一个例子说明Get.put的用法。

        在这个例子中,我们在首页操作计时器,然后在收藏页面调用HomeController中的计时器的点击次数。

图1.Get.put用法

        我们来看看如何实现这个功能。

        1.首先我们创建一个控制器,它包含计数逻辑。

class HomeController extends GetxController {var count = 0.obs;void increment() {count++;}
}

        2.在应用启动时注入依赖

        在 main 方法中使用 Get.put 将 CounterController 注入到依赖管理系统中。

void main() {// 注入依赖Get.put(HomeController());runApp(const MyApp());
}

        3.在页面中使用依赖

        完整代码:

import 'package:flutter/material.dart';
import 'package:get/get.dart';class DependencyManagerMain extends StatefulWidget {const DependencyManagerMain({super.key});@overrideState<DependencyManagerMain> createState() => _DependencyManagerMainState();
}class _DependencyManagerMainState extends State<DependencyManagerMain>with SingleTickerProviderStateMixin {late TabController _tabController;@overridevoid initState() {super.initState();// 初始化 TabController_tabController = TabController(length: 3, vsync: this);}@overridevoid dispose() {// 销毁 TabController_tabController.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: TabBarView(controller: _tabController,children: [HomePage(),FavoritesTab(),const SettingsTab(),],),bottomNavigationBar: TabBar(controller: _tabController,tabs: const [Tab(icon: Icon(Icons.home), text: "首页"),Tab(icon: Icon(Icons.star), text: "收藏"),Tab(icon: Icon(Icons.settings), text: "设置"),],),);}
}class HomeController extends GetxController {var count = 0.obs;void increment() {count++;}
}
class HomePage extends StatelessWidget {HomePage({super.key});final HomeController controller = Get.find<HomeController>();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('首页'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 使用 Obx 来监听 count 的变化Obx(() => Text('Count: ${controller.count}',style: const TextStyle(fontSize: 20),)),const SizedBox(height: 20),ElevatedButton(onPressed: controller.increment,child: const Text('Increment'),),],),),);}
}class FavoritesTab extends StatelessWidget {FavoritesTab({super.key});final HomeController controller = Get.find<HomeController>();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('收藏'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 使用 Obx 来监听 count 的变化Obx(() => Text('点击次数: ${controller.count}',style: const TextStyle(fontSize: 20),)),const SizedBox(height: 20),],),),);}
}class SettingsTab extends StatelessWidget {const SettingsTab({super.key});@overrideWidget build(BuildContext context) {return const Center(child: Text('Settings Tab Content'),);}
}

2.Get.lazyPut

        可以懒加载一个依赖,这样它只有在使用时才会被实例化。这对于计算代价高的类来说非常有用,或者如果你想在一个地方实例化几个类(比如在Bindings类中),而且你知道你不会在那个时候使用这个类。
        Get.lazyPut方法用于延迟创建依赖实例,只有在第一次使用时才会创建。

        这里就不写demo了,感兴趣的话,可以参考上一个例子中的demo写Demo测试一下。

///只有当第一次使用Get.find<ApiMock>时,ApiMock才会被调用。
Get.lazyPut<ApiMock>(() => ApiMock());

Get.lazyPut<FirebaseAuth>(
  () {
    // ... some logic if needed
    return FirebaseAuth();
  },
  tag: Math.random().toString(),
  fenix: true
)

Get.lazyPut<Controller>( () => Controller() )

3.Get.putAsync

        如果你想注册一个异步实例,你可以使用Get.putAsync
        Get.putAsync方法用于异步创建依赖实例,适用于需要进行异步操作的实例化过程。

Get.putAsync<SharedPreferences>(() async {final prefs = await SharedPreferences.getInstance();await prefs.setInt('counter', 12345);return prefs;
});Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )

        我们还可以设置如下参数:

Get.putAsync<S>(

  // 必备:一个将被执行的异步方法,用于实例化你的类。
  AsyncInstanceBuilderCallback<S> builder,

  // 可选:和Get.put()一样,当你想让同一个类有多个不同的实例时,就会用到它。
  // 必须是唯一的
  String tag,

  // 可选:与Get.put()相同,当你需要在整个应用程序中保持该实例的生命时使用。
  // 默认值为false
  bool permanent = false
)

4.GetView、GetxView 和GetxController

4.高级依赖注入

1.使用Get.create

        Get.create方法用于每次请求时创建一个新的依赖实例,适用于需要多次创建的依赖。

void main() {Get.create<MyController>(() => MyController());runApp(MyApp());
}

2.依赖生命周期管理

        GetX 提供了三种依赖生命周期管理模式:

        Permanent:永久存在,直到应用关闭。

        Singleton:默认模式,实例在第一次创建后存在于整个应用生命周期内。

        Transient:每次请求时创建新的实例。

        模块化依赖注入:
         在大型项目中,可以将依赖注入模块化,便于管理和维护。

class AppBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<MyController>(() => MyController());
  }
}

void main() {
  runApp(GetMaterialApp(
    initialBinding: AppBinding(),
    home: MyApp(),
  ));
}

5.依赖管理中的常见问题及解决方案

1.依赖未能正确注入或找到

        例如在下面的例子中,我在首页调用Get.find的方法,但是想相应的实例方法却没有被创建。

CounterController counterController = Get.find();

图2.依赖未能正确注入或找到

        控制台日志输出如下:

        图3.控制台输入日志

        解决的方法也很简单,就是在调用之前确保相应的GetxController被实例化。

        例如我们可以在app启动之前,实例化相应的控制器或者初始化的时候就绑定相应的GetxController。

图3.全局绑定GetxController

2.实例化过程中的性能问题

        在使用 GetX 时,如果不小心,可能会引入性能问题。例如,不恰当地更新整个 UI 而不是局部更新,或者频繁地创建和销毁控制器。下面是一个示例,展示了如何使用 GetX 并说明可能的性能问题,以及如何优化这些问题。

        在下面的代码中,PerformancelssueExample类展示了可能的性能问题。每次计数器值变化时,整个 Column 会被重建,导致性能下降。

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return GetMaterialApp(home: HomePage(),);}
}class HomeController extends GetxController {var counter = 0.obs;void increment() => counter.value++;
}class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {final HomeController controller = Get.put(HomeController());return Scaffold(appBar: AppBar(title: Text('GetX Performance Example'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('You have pushed the button this many times:'),GetX<HomeController>(builder: (controller) {return Text('${controller.counter.value}',style: Theme.of(context).textTheme.headline4,);},),PerformanceIssueExample(),],),),floatingActionButton: FloatingActionButton(onPressed: controller.increment,tooltip: 'Increment',child: Icon(Icons.add),),);}
}class PerformanceIssueExample extends StatelessWidget {@overrideWidget build(BuildContext context) {final HomeController controller = Get.find();return Column(children: [Obx(() {print("Rebuilding entire Column");return Column(children: [for (int i = 0; i < 100; i++)Text('Item $i'),Text('Counter: ${controller.counter.value}'),],);}),ElevatedButton(onPressed: controller.increment,child: Text('Increment Counter'),),],);}
}

         优化建议:

  1. 避免在可观察值变化时重建整个组件树。
  2. 将变化范围限制在最小的部件中,以减少重建次数

  3. 使用 GetX 或 Obx 只在必要时更新 UI

3.依赖生命周期管理不当导致的内存泄漏

       在使用 GetX 时,内存管理是一个重要的考虑因素。如果不正确地管理控制器和依赖项,可能会导致内存泄漏。下面是一个示例,说明 GetX 内存管理中的常见问题及其解决方案。

1.示例代码

        假设我们有一个简单的计数器应用,每次进入一个新页面都会创建一个新的控制器实例,但未正确释放旧的控制器实例,这会导致内存泄漏。

        以下面代码为例:

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(MyApp());
}class CounterController extends GetxController {var count = 0.obs;void increment() => count++;
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return GetMaterialApp(home: HomePage(),);}
}class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Home Page'),),body: Center(child: ElevatedButton(onPressed: () {Get.to(CounterPage());},child: Text('Go to Counter Page'),),),);}
}class CounterPage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 不推荐的做法:每次进入页面时创建新的控制器实例final CounterController controller = Get.put(CounterController());return Scaffold(appBar: AppBar(title: Text('Counter Page'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[GetX<CounterController>(builder: (_) {return Text('Count: ${controller.count.value}');},),ElevatedButton(onPressed: controller.increment,child: Text('Increment'),),],),),);}
}

        在这个示例中,每次导航到 CounterPage 时,都会创建一个新的 CounterController 实例,但未正确释放旧的实例,这会导致内存泄漏。

2.解决方案

        为了避免内存泄漏,可以使用 Get.put 或 Get.lazyPut 在合适的地方创建和释放控制器实例,并使用 Get.delete 方法在不需要时释放控制器实例。

        修改后的代码如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(MyApp());
}class CounterController extends GetxController {var count = 0.obs;void increment() => count++;
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return GetMaterialApp(home: HomePage(),);}
}class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Home Page'),),body: Center(child: ElevatedButton(onPressed: () {Get.to(CounterPage());},child: Text('Go to Counter Page'),),),);}
}class CounterPage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 推荐的做法:使用 Get.put 只创建一个控制器实例,直到不再需要final CounterController controller = Get.put(CounterController());return Scaffold(appBar: AppBar(title: Text('Counter Page'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[GetX<CounterController>(builder: (_) {return Text('Count: ${controller.count.value}');},),ElevatedButton(onPressed: controller.increment,child: Text('Increment'),),],),),);}@overridevoid dispose() {// 当页面销毁时,释放控制器实例Get.delete<CounterController>();super.dispose();}
}

        修改之后的实例中:

1.正确使用Get.put:在 CounterPage 页面创建时,只创建一个 CounterController 实例。

2.使用Get.put和Get.lazyPut:根据需要创建和管理控制器实例。

3.释放控制器实例:在页面销毁时,通过 Get.delete<CounterController>() 方法释放控制器实例,防止内存泄漏。

6. 参考资料

        1.Getx官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/380949.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESP8266模块(2)

实例1 查看附近的WiFi 步骤1&#xff1a;进入AT指令模式 使用USB转串口适配器将ESP8266模块连接到电脑。打开串口终端软件&#xff0c;并设置正确的串口和波特率&#xff08;通常为115200&#xff09;。输入以下命令并按回车确认&#xff1a; AT如果模块响应OK&#xff0c;…

R语言包AMORE安装报错问题以及RStudio与Rtools环境配置

在使用R语言进行AMORE安装时会遇到报错,这时候需要采用解决办法: AMORE包安装,需要离线官网下载安装包: Index of /src/contrib/Archive/AMORE (r-project.org)https://cran.r-project.org/src/contrib/Archive/AMORE/ 一、出现的问题 最近开始学习R语言,安装了最新版…

Window中 Redis下载安装

Redis7.2.3连接&#xff1a; 我用夸克网盘分享了「redis-windows-7.2.3.zip」&#xff0c;点击链接即可保存。打开「夸克APP」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/4dfb0497707a 在安…

义务外贸wordpress独立站主题

健身器材wordpress网站模板 跑步机、椭圆机、划船机、动感单车、健身车、深蹲架、龙门架、健身器材wordpress网站模板。 https://www.jianzhanpress.com/?p4251 农业机械wordpress网站模板 植保机械、畜牧养殖机械、农机配件、土壤耕整机械、农业机械wordpress网站模板。 …

WebRTC音视频-前言介绍

目录 效果预期 1&#xff1a;WebRTC相关简介 1.1&#xff1a;WebRTC和RTC 1.2&#xff1a;WebRTC前景和应用 2&#xff1a;WebRTC通话原理 2.1&#xff1a;媒体协商 2.2&#xff1a;网络协商 2.3&#xff1a;信令服务器 效果预期 1&#xff1a;WebRTC相关简介 1.1&…

Windows FFmpeg 开发环境搭建

FFmpeg 开发环境搭建 FFmpeg命令行环境搭建使用FFmpeg官方编译的库Windows编译FFmpeg1. 下载[msys2](https://www.msys2.org/#installation)2. 安装完成之后,将安装⽬录下的msys2_shell.cmd中注释掉的 rem set3. 修改pacman 镜像源并安装依赖4. 下载并编译源码 FFmpeg命令行环境…

Python PDF Magic:合并和拆分随心所欲

大家好&#xff01;小编今天要为大家带来一篇关于Python操作PDF的秘籍——无论是要将PDF合并成一份整体&#xff0c;还是将一个庞大的PDF文件拆分成多个小伙伴&#xff0c;都轻松hold住&#xff01;你准备好了吗&#xff1f;让我们开始这场奇妙的PDF操作之旅吧&#xff01; 准…

C++基础入门(二)(函数重载,引用,内联函数,nullptr)

目录 一. 函数重载 1. 概念 2. 实现 (1). 参数类型不同 (2). 参数个数不同 (3). 参数类型顺序不同 3. 注意事项 (1). 返回值不能作为重载的条件 (2). 不能仅按函数返回类型重载 (3). 与缺省参数的问题 二. 引用 1. 概念和定义 2. 引用的特性 (1). 引用在定义时必须…

【多任务YOLO】 A-YOLOM: You Only Look at Once for Real-Time and Generic Multi-Task

You Only Look at Once for Real-Time and Generic Multi-Task 论文链接&#xff1a;http://arxiv.org/abs/2310.01641 代码链接&#xff1a;https://github.com/JiayuanWang-JW/YOLOv8-multi-task 一、摘要 高精度、轻量级和实时响应性是实现自动驾驶的三个基本要求。本研究…

HTML5实现好看的天气预报网站源码

文章目录 1.设计来源1.1 获取天气接口1.2 PC端页面设计1.3 手机端页面设计 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_4…

深入理解PHP基础【代码审计实战指南】

文章目录 基础语法单双引号的区别前后端分离数据类型PHP常量函数var_dump函数count函数print_r函数**readfile&#xff08;&#xff09;函数****file_get_contents()函数****file_put_contents()函数**header函数fopen函数fread 函数rename函数copy&#xff08;&#xff09;函数…

【Android】视图与常用控件总结

文章目录 一、视图基础1.1 设置视图的宽高1.2 设置视图的间距1.3 设置视图的对齐方式1.4 总结 二、控件2.1 TextView2.1.1 设置宽高2.1.2 设置内容2.1.3 设置大小2.1.4 设置颜色 2.2 Button2.3 EditText2.4 ImageView2.5 ProgressBar2.6 AlertDialog2.7 ProgressDialog 本文主要…

EVM-MLIR:以MLIR编写的EVM

1. 引言 EVM_MLIR&#xff1a; 以MLIR编写的EVM。 开源代码实现见&#xff1a; https://github.com/lambdaclass/evm_mlir&#xff08;Rust&#xff09; 为使用MLIR和LLVM&#xff0c;将EVM-bytecode&#xff0c;转换为&#xff0c;machine-bytecode。LambdaClass团队在2周…

RICHTEK立锜科技 WIFI 7电源参考设计

什么是WIFI 7? WiFi 7&#xff08;Wi-Fi 7&#xff09;是下一代Wi-Fi标准&#xff0c;对应的是IEEE 802.11将发布新的修订标准IEEE 802.11be –极高吞吐量EHT&#xff08;Extremely High Throughput &#xff09;。Wi-Fi 7是在Wi-Fi 6的基础上引入了320MHz带宽、4096-QAM、Mu…

手动构建线性回归(PyTorch)

import torch from sklearn.datasets import make_regression import matplotlib.pyplot as plt import random #1.构建数据 #构建数据集 def create_dataset():x,y,coefmake_regression(n_samples100,n_features1,random_state0,noise10,coefTrue,bias14.5)#将构建数据转换为张…

H3CNE(计算机网络的概述)

1. 计算机网络的概述 1.1 计算机网络的三大基本功能 1. 资源共享 2. 分布式处理与负载均衡 3. 综合信息服务 1.2 计算机网络的三大基本类型 1.3 网络拓扑 定义&#xff1a; 网络设备连接排列的方式 网络拓扑的类型&#xff1a; 总线型拓扑&#xff1a; 所有的设备共享一…

# Redis 入门到精通(九)-- 主从复制(1)

Redis 入门到精通&#xff08;九&#xff09;-- 主从复制&#xff08;1&#xff09; 一、redis 主从复制 – 主从复制简介 1、互联网“三高”架构 高并发高性能高可用 2、你的“Redis”是否高可用&#xff1f; 1&#xff09;单机 redis 的风险与问题 问题1.机器故障  现…

代码随想录算法训练营第九天 |LeetCode151.翻转字符串里的单词 卡码网:55.右旋转字符串

代码随想录算法训练营 Day 9 代码随想录算法训练营第九天 |LeetCode151.翻转字符串里的单词 卡码网&#xff1a;55.右旋转字符串 目录 代码随想录算法训练营前言LeetCode151.翻转字符串里的单词卡码网&#xff1a;55.右旋转字符串 一、LeetCode151.翻转字符串里的单词1.题目链…

[Cesium for Supermap] 加载3dTiles,点击获取属性

代码&#xff1a; // 设为椭球var obj [6378137.0, 6378137.0, 6356752.3142451793];Cesium.Ellipsoid.WGS84 Object.freeze(new Cesium.Ellipsoid(obj[0], obj[1], obj[2]));var viewer new Cesium.Viewer(cesiumContainer);var scene viewer.scenescene.lightSource.ambi…

python 打包

#导出依赖文件列表 pip freeze > requirements.txt #安装对应文件 pip install -r requirements.txt #将依赖打成对应whl文件 pip wheel --wheel-dir ./dist -r ./requirements.txt #安装whl文件 pip install …whl