目录

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:反应式,只在依赖的变量变化时更新。

 1class 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支持的,您可以任选其中一种您喜欢的方式。

 1final count = Rx<int>(0);

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

        完整代码如下:

 1import '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的控制器,代码如下:

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

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

 1class 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变量,代码如下:

 1class GetBuilderController extends GetxController {

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

        完整的代码如下:

 1import '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 变量每次变化时调用回调函数。

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

2.everAll

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

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

3.once

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

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

4.interval

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

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

5.debounce

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

 1import '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。

 1import '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将只被再次重建)

个人笔记记录 2021 ~ 2025