首页/文章/flutter

Flutter中GetX的用法(超详细使用指南之状态管理篇)

2024-10-25
309611 分钟
...

目录

1. 引言

 2.安装和配置 GetX

3.GetX 状态管理的核心概念

1.响应式编程

2.控制器 (Controller)

3.状态 (State)

4.状态更新(State Update)

 5. 基本用法示例

1.Obx

 2.GetX

3.GetBuilder

4.Workers

1.ever

2.everAll

3.once

4.interval

5.debounce

6.Workers完整示例

5.唯一的ID


1. 引言

        在 Flutter 开发中,状态管理是一个至关重要的概念。它决定了应用的性能和维护性。GetX 是一个强大的 Flutter 包,它提供了高效、简洁的状态管理、依赖管理和路由管理功能。本文将深入探讨 GetX 的状态管理,并展示如何在 Flutter 应用中使用它。

        Flutter也有其它的状态管理器,它们有着各自的特点:

  1. BLoC非常安全和高效,但是对于初学者来说非常复杂,这使得人们无法使用Flutter进行开发。
  2. MobX比BLoC更容易,而且是响应式的,几乎是完美的,但是你需要使用一个代码生成器,对于大型应用来说,这降低了生产力,因为你需要喝很多咖啡,直到你的代码在flutter clean之后再次准备好(这不是MobX的错,而是codegen真的很慢!)。
  3. Provider使用InheritedWidget来传递相同的监听器,以此来解决上面报告的ChangeNotifier的问题,这意味着对其ChangeNotifier类的任何访问都必须在widget树内。

        Get并不是比任何其他状态管理器更好或更差,而是说你应该分析这些要点以及下面的要点来选择是只用Get,还是与其他状态管理器结合使用。Get不是其他状态管理器的敌人,因为Get是一个微框架,而不仅仅是一个状态管理器,它的状态管理功能既可以单独使用,也可以与其他状态管理器结合使用。

 2.安装和配置 GetX

        要在 Flutter 项目中使用 GetX,需要在 pubspec.yaml 文件中添加 GetX 依赖:。

dependencies:
  get: ^4.6.6

        然后,在需要使用 GetX 的文件中导入它:

import 'package:get/get.dart';

3.GetX 状态管理的核心概念

1.响应式编程

          GetX 的状态管理基于响应式编程,这意味着状态的变化会自动更新依赖该状态的 UI。GetX 通过 Rx 类及其子类(如 RxInt、RxString)实现了响应式编程。

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

  void increment() {
    count++;
  }
}

        在上面的代码中,count 是一个可观察的整数 (RxInt)。当 count 的值改变时,任何依赖它的 UI 会自动更新。

2.控制器 (Controller)

          控制器用于管理状态和业务逻辑。它继承自 GetxController,可以在其中定义可观察变量和方法。

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

  void increment() {
    count++;
  }
}

        在这个例子中,MyController 管理 count 状态和 increment 方法。

3.状态 (State)

          状态是应用程序的当前数据或信息。在 GetX 中,可以使用 .obs 修饰符来声明可观察变量,并使用 update() 方法手动触发更新。

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

  void increment() {
    count++;
  }
}

        通过 count 的 .obs 修饰符,count 变成了一个可观察变量。

4.状态更新(State Update)

        GetX 提供了多种更新状态的方法,包括 GetBuilder、GetX 和 Obx。

        GetBuilder:非反应式,只在 update() 调用时更新。

        GetX 和 Obx:反应式,只在依赖的变量变化时更新。

class HomePage extends StatelessWidget {final MyController controller = Get.put(MyController());  Widget build(BuildContext context) {      appBar: AppBar(title: Text('GetX Example')),          mainAxisAlignment: MainAxisAlignment.center,return Text('Count: ${controller.count}');              onPressed: controller.increment,              child: Text('Increment'),

 5. 基本用法示例

1.Obx

        以下图的效果为例。我们有两个变量,counter1,counter2和sum.其中sum = counter1+counter2.当我们更新counter1或者Counter2其中的一个变量,sum变量就可自动更新。

图1.计时器        

        我们看看如何实现。

        首先我们把变量生成Getx的Rx类型。

        下面这个三种写法都是Getx支持的,您可以任选其中一种您喜欢的方式。

final count = Rx<int>(0);

        然后再使用到该变量的Widget外面使用它Obx包起来即可。

        完整代码如下:

import 'package:flutter/material.dart';import 'package:get/get.dart';class ObxDemosPage extends StatelessWidget {  ObxDemosPage({super.key});final count = Rx<int>(0);  Widget build(BuildContext context) {        title: const Text('ObX Demos'),              mainAxisAlignment: MainAxisAlignment.spaceEvenly,                Obx(()=> Text('counter1:${counter1.value.toInt()}'),),                  child: const Text('counter1++'),const SizedBox(height: 16.0),              mainAxisAlignment: MainAxisAlignment.spaceEvenly,                Obx(()=> Text('counter2:${counter2.value.toInt()}'),),                  child: const Text('counter2++'),const SizedBox(height: 16.0),            Obx(()=> Text('sum:${counter2.value.toInt()+counter1.value.toInt()}'),),

 2.GetX

        还是上述图1的功能为例,我们还可以使用GetxController来实现。

        顾名思义,controller也就是控制器的意思,这个类的出现是为了减少代码的低耦合。

        我们把业务代码放到GetxController中,减少Widget部分的代码。

        我们定义一个继承自GetxController的控制器,代码如下:

class Controller extends GetxController {int get sum => count1.value + count2.value;

        然后我们使用GetX包在Widget的外层,即可对变量的精准控制。       

class GetXCounterPage extends StatelessWidget {  GetXCounterPage({super.key});final Controller controller = Get.put(Controller());  Widget build(BuildContext context) {        title: const Text('计时器Demo'),          mainAxisAlignment: MainAxisAlignment.start,              mainAxisAlignment: MainAxisAlignment.spaceEvenly,print("count 1 rebuild");return Text('count1: ${controller.count1.value}');                  onPressed: controller.incrementCount1,                  child: const Text('Increment Count1'),              mainAxisAlignment: MainAxisAlignment.spaceEvenly,                    debugPrint("count 2 rebuild");return Text('count2: ${controller.count2.value}');                  onPressed: controller.incrementCount2,                  child: const Text('Increment Count2'),                debugPrint("sum rebuild");return Text('sum: ${controller.sum}');

        上述的过程是自动的,也就是当我们调用GexController中的方法之后,被观察的值立即改变。

3.GetBuilder

        GetBuilder的用法和GetX基本相同。区别就是如果使用GetBuilder必须手动的调用GetxController的update方法页面才会刷新。

        以下图为例,我们我们的控制器有一个count变量,代码如下:

class GetBuilderController extends GetxController {

        当我们点击按钮之后,调用incrementCount方法,count的值并不会马上更新,只有手动的调用update方法,count才会更新。

        完整的代码如下:

import 'package:flutter/material.dart';import 'package:get/get.dart';class GetBuilderController extends GetxController {class GetBuilderDemosPage extends StatelessWidget {  GetBuilderDemosPage({super.key});final GetBuilderController controller = Get.put(GetBuilderController());  Widget build(BuildContext context) {        title: const Text('计时器Demo'),          mainAxisAlignment: MainAxisAlignment.start,            GetBuilder<GetBuilderController>(                debugPrint("count rebuild");return Text('count: ${controller.count.value}');              onPressed: controller.incrementCount,              child: const Text('increment'),              onPressed: controller.update,              child: const Text('update'),

图2.GetBuilder

4.Workers

        在 GetX 中,Workers 是一种监控和响应 Rx 类型变量变化的机制。它们可以在变量变化时执行特定的回调函数,帮助开发者简化逻辑处理和状态更新。Workers 包括以下几种类型:

        ever、everAll、once、interval、debounce

1.ever

ever 会在指定的 Rx 变量每次变化时调用回调函数。

class Controller extends GetxController {int get sum => count1.value + count2.value;      debugPrint("Count changed: $count2");

2.everAll

everAll 会在多个指定的 Rx 变量中的任意一个变化时调用回调函数。

class MyController extends GetxController {    everAll([count1, count2], (_) {print("One of the counts changed: count1 = $count1, count2 = $count2");

3.once

once 只会在指定的 Rx 变量第一次变化时调用回调函数。

class MyController extends GetxController {print("Count changed for the first time: $count");

4.interval

interval 会在指定的 Rx 变量变化时调用回调函数,但在指定时间内只会调用一次,适用于减少频繁更新的场景。

class MyController extends GetxController {print("Count changed (with interval): $count");    }, time: Duration(seconds: 1));

5.debounce

debounce 会在指定的 Rx 变量变化后的一段时间内没有再次变化时调用回调函数,适用于处理用户输入等场景。

import 'package:flutter/material.dart';import 'package:get/get.dart';class MyController extends GetxController {print("Count1 changed: $count1");    everAll([count1, count2], (_) {print("Count1 or Count2 changed: count1 = $count1, count2 = $count2");print("Count1 changed for the first time: $count1");print("Count1 changed (with interval): $count1");    }, time: Duration(seconds: 1));print("Count1 changed (debounced): $count1");    }, time: Duration(seconds: 1));class MyApp extends StatelessWidget {  Widget build(BuildContext context) {class HomeScreen extends StatelessWidget {final MyController controller = Get.put(MyController());  Widget build(BuildContext context) {        title: Text('GetX Workers Example'),          mainAxisAlignment: MainAxisAlignment.center,            Obx(() => Text('Count1: ${controller.count1}')),            Obx(() => Text('Count2: ${controller.count2}')),              onPressed: controller.incrementCount1,              child: Text('Increment Count1'),              onPressed: controller.incrementCount2,              child: Text('Increment Count2'),

6.Workers完整示例

以下是一个完整示例,展示了如何在 GetX 中使用 Workers。

import 'package:flutter/material.dart';import 'package:get/get.dart';class MyController extends GetxController {print("Count1 changed: $count1");    everAll([count1, count2], (_) {print("Count1 or Count2 changed: count1 = $count1, count2 = $count2");print("Count1 changed for the first time: $count1");print("Count1 changed (with interval): $count1");    }, time: Duration(seconds: 1));print("Count1 changed (debounced): $count1");    }, time: Duration(seconds: 1));class MyApp extends StatelessWidget {  Widget build(BuildContext context) {class HomeScreen extends StatelessWidget {final MyController controller = Get.put(MyController());  Widget build(BuildContext context) {        title: Text('GetX Workers Example'),          mainAxisAlignment: MainAxisAlignment.center,            Obx(() => Text('Count1: ${controller.count1}')),            Obx(() => Text('Count2: ${controller.count2}')),              onPressed: controller.incrementCount1,              child: Text('Increment Count1'),              onPressed: controller.incrementCount2,              child: Text('Increment Count2'),

5.唯一的ID

        如果你想用GetBuilder完善一个widget的更新控件,你可以给它们分配唯一的ID。

GetBuilder(
  id: 'text', //这里
  init: Controller(), // 每个控制器只用一次
  builder: (_) => Text(
    '${Get.find().counter}', //here
  ),
),

        并更新它:

update(['text']);

        GetX会自动进行重建,并且只重建使用被更改的变量的小组件,如果您将一个变量更改为与之前相同的变量,并且不意味着状态的更改,GetX不会重建小组件以节省内存和CPU周期(界面上正在显示3,而您再次将变量更改为3。在大多数状态管理器中,这将导致一个新的重建,但在GetX中,如果事实上他的状态已经改变,那么widget将只被再次重建)

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
flutter2026-07-01
Dart 入门回顾
1\. Dart 是什么 Dart 是一门类型安全、支持面向对象、支持异步编程的语言。它的语法和 JavaScript、TypeScript、Java、C# 都有一些相似之处。 Dart 常见使用场景: Flutter 跨平台应用开发 命令行工具 Web 应用 服务端接口或脚本 作为学习现代类型语言的入口 Dart 的几个核心特点: 静态类型:变量、函数返回值、参数都有类型。 类型推断:很多时候可以用 ,让 Dart 自动推断类型。 空...
学习
flutter2026-07-01
Flutter 常用 Widget 入门
Flutter 的核心思想是:一切皆 Widget。文字、图片、按钮、页面结构、布局、间距、滚动、动画、手势,几乎都由 Widget 组合出来。 1\. Widget 先分成几类理解 | 类别 | 常用 Widget | 解决什么问题 | | | | | | 应用入口 | 、 | 搭建应用外壳、主题、路由 | | 页面骨架 | 、 、 | 标准页面结构 | | 基础显示 | 、 、 | 显示文字、图标、图片 | | 布局容器 | 、 、...
学习
flutter2024-11-21
在 Flutter 中使用 webview_flutter 4.0
1. 2. ,已入选 3. 4. 本文是第 4 篇,定位是新手入门,介绍和演示 webview 的基础用法。最后还介绍了事件处理的技巧。因为是补写的,所以本来应该首发的却发在最后了。 环境准备已经在 说过了,不再赘述。既然是新手入门,就会本着详尽的原则,而且会多配示例。 获取页面信息 获取页面 title 核心方法:controller.getTitle 完整示例,放在 main.dart 就能运行。运行示例,点击获取 title 的按...
学习
flutter2024-11-06
flutter android端运行报错Namespace not specified. Specify a namespace in the module‘s build file
在使用flutterSDK 3.24之后发现新建项目,项目默认都是基于AGP8了,由于 AGP 开始强制要求 namespace 配置,不仅仅是主工程,也包括第三方库都强制要求 namespace 。但是我们在引入第三方库的时候会发现部分库没能及时的去做相关配置,这也就导致了我们会出现标题错误: 出现这个问题,我们可能会通过去找到本地缓存的第三方库代码去修改它的build.gradle和AndroidManifest.xml来解决缺失...
学习
flutter2024-11-03
Flutter中如何实现APP升级功能背景
背景 每个App应用中一定会包含的功能 ,App的运行平台不同实现升级功能的方式也就不同,基本分类如下所示。本文主要聚焦在使用Flutter框架开发的应用在安卓系统内如何更新,以及所涉及要点梳理。 IOS系统 Andriod系统 官网下载 各类应用市场 (本文聚焦点) 功能清单(按步骤) UpgradeCard组件(展示升级内容) 进行新旧版本对比判断是否需要更新 下载更新然后安装应用 UpgradeCard组件 组件需要包含基本标题、...
学习
flutter2024-11-03
Flutter应用内更新App版本使用flutter_downloader而非ota_update
做当前App应用内更新的前提:用户可以在App更新的时候还可以使用软件,不能让他一直等待下载,关闭下载组件后,打开组件还能继续看到他的进度,并且用户锁屏或者短暂退出APP后需要保证任务不能总是挂掉,这里没有用到保活,而是需要用到生命周期去让他暂停和恢复,所以当前app还要有一个全局管理类保存任务id。UI图在最后 (插件文档说明可以通知栏显示,但是我用的这个版本在100%下完后总是failed,而不是complete,就不会很友好,后面...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录