深入浅出 GetX:超具体实用指南,全方位掌握 Flutter 开发利器第二篇之状态 ...

打印 上一主题 下一主题

主题 1115|帖子 1115|积分 3345

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x


目录
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也有别的的状态管理器,它们有着各自的特点:

  • BLoC非常安全和高效,但是对于初学者来说非常复杂,这使得人们无法利用Flutter举行开发。
  • MobX比BLoC更容易,而且是相应式的,几乎是完善的,但是你需要利用一个代码生成器,对于大型应用来说,这降低了生产力,因为你需要喝很多咖啡,直到你的代码在flutter clean之后再次准备好(这不是MobX的错,而是codegen真的很慢!)。
  • 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:反应式,只在依靠的变量变化时更新。
  1. class HomePage extends StatelessWidget {
  2.   final MyController controller = Get.put(MyController());
  3.   @override
  4.   Widget build(BuildContext context) {
  5.     return Scaffold(
  6.       appBar: AppBar(title: Text('GetX Example')),
  7.       body: Center(
  8.         child: Column(
  9.           mainAxisAlignment: MainAxisAlignment.center,
  10.           children: [
  11.             GetX<MyController>(
  12.               builder: (controller) {
  13.                 return Text('Count: ${controller.count}');
  14.               },
  15.             ),
  16.             ElevatedButton(
  17.               onPressed: controller.increment,
  18.               child: Text('Increment'),
  19.             ),
  20.           ],
  21.         ),
  22.       ),
  23.     );
  24.   }
  25. }
复制代码
 5. 根本用法示例

1.Obx

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

图1.计时器        

        我们看看如何实现。
        首先我们把变量生成Getx的Rx范例。
        下面这个三种写法都是Getx支持的,您可以任选此中一种您喜欢的方式。
  1.   var counter1 = 0.obs;
  2.   final count = Rx<int>(0);
  3.   final counter2 = Rx(0);
复制代码
        然后再利用到该变量的Widget外面利用它Obx包起来即可。
        完整代码如下:
  1. import 'package:flutter/material.dart';import 'package:get/get.dart';class ObxDemosPage extends StatelessWidget {  ObxDemosPage({super.key});  var counter1 = 0.obs;
  2.   final count = Rx<int>(0);
  3.   final counter2 = Rx(0);  // var counter2 = 0.obs;  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: const Text('ObX Demos'),      ),      body: Center(        child:Column(          children: [            Row(              mainAxisAlignment: MainAxisAlignment.spaceEvenly,              children: [                Obx(()=> Text('counter1:${counter1.value.toInt()}'),),                ElevatedButton(                  onPressed: () {                    counter1.value++;                  },                  child: const Text('counter1++'),                ),              ],            ),            const SizedBox(height: 16.0),            Row(              mainAxisAlignment: MainAxisAlignment.spaceEvenly,              children: [                Obx(()=> Text('counter2:${counter2.value.toInt()}'),),                ElevatedButton(                  onPressed: () {                    counter2.value++;                  },                  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的控制器,代码如下:
  1. class Controller extends GetxController {
  2.   final count1 = 0.obs;
  3.   final count2 = 0.obs;
  4.   // sum 的值为 count1 和 count2 的总和
  5.   int get sum => count1.value + count2.value;
  6.   // 增加 count1 的值
  7.   void incrementCount1() {
  8.     count1.value++;
  9.   }
  10.   // 增加 count2 的值
  11.   void incrementCount2() {
  12.     count2.value++;
  13.   }
  14. }
复制代码
        然后我们利用GetX包在Widget的外层,即可对变量的精准控制。       
  1. class GetXCounterPage extends StatelessWidget {
  2.   GetXCounterPage({super.key});
  3.   // 使用 Get.put 以确保控制器实例在需要时被正确管理
  4.   final Controller controller = Get.put(Controller());
  5.   @override
  6.   Widget build(BuildContext context) {
  7.     return Scaffold(
  8.       appBar: AppBar(
  9.         title: const Text('计时器Demo'),
  10.       ),
  11.       body: Center(
  12.         child: Column(
  13.           mainAxisAlignment: MainAxisAlignment.start,
  14.           children: [
  15.             Row(
  16.               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  17.               children: [
  18.                 GetX<Controller>(
  19.                   builder: (controller) {
  20.                     print("count 1 rebuild");
  21.                     return Text('count1: ${controller.count1.value}');
  22.                   },
  23.                 ),
  24.                 ElevatedButton(
  25.                   onPressed: controller.incrementCount1,
  26.                   child: const Text('Increment Count1'),
  27.                 ),
  28.               ],
  29.             ),
  30.             Row(
  31.               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  32.               children: [
  33.                 GetX<Controller>(
  34.                   builder: (controller) {
  35.                     debugPrint("count 2 rebuild");
  36.                     return Text('count2: ${controller.count2.value}');
  37.                   },
  38.                 ),
  39.                 ElevatedButton(
  40.                   onPressed: controller.incrementCount2,
  41.                   child: const Text('Increment Count2'),
  42.                 ),
  43.               ],
  44.             ),
  45.             GetX<Controller>(
  46.               builder: (controller) {
  47.                 debugPrint("sum rebuild");
  48.                 return Text('sum: ${controller.sum}');
  49.               },
  50.             ),
  51.           ],
  52.         ),
  53.       ),
  54.     );
  55.   }
  56. }
复制代码
        上述的过程是自动的,也就是当我们调用GexController中的方法之后,被观察的值立即改变。
3.GetBuilder

        GetBuilder的用法和GetX根本相同。区别就是假如利用GetBuilder必须手动的调用GetxController的update方法页面才会刷新。
        以下图为例,我们我们的控制器有一个count变量,代码如下:
  1. class GetBuilderController extends GetxController {
  2.   final count = 0.obs;
  3.   void incrementCount() {
  4.     count.value++;
  5.   }
  6. }
复制代码
        当我们点击按钮之后,调用incrementCount方法,count的值并不会马上更新,只有手动的调用update方法,count才会更新。
        完整的代码如下:
  1. import 'package:flutter/material.dart';import 'package:get/get.dart';class GetBuilderController extends GetxController {
  2.   final count = 0.obs;
  3.   void incrementCount() {
  4.     count.value++;
  5.   }
  6. }class GetBuilderDemosPage extends StatelessWidget {  GetBuilderDemosPage({super.key});  // 利用 Get.put 以确保控制器实例在需要时被精确管理  final GetBuilderController controller = Get.put(GetBuilderController());  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: const Text('计时器Demo'),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.start,          children: [            GetBuilder<GetBuilderController>(              builder: (controller) {                debugPrint("count rebuild");                return Text('count: ${controller.count.value}');              },            ),            ElevatedButton(              onPressed: controller.incrementCount,              child: const Text('increment'),            ),            ElevatedButton(              onPressed: controller.update,              child: const Text('update'),            ),          ],        ),      ),    );  }}
复制代码

图2.GetBuilder

4.Workers

        在 GetX 中,Workers 是一种监控和相应 Rx 范例变量变化的机制。它们可以在变量变化时执行特定的回调函数,帮助开发者简化逻辑处置惩罚和状态更新。Workers 包括以下几种范例:
        ever、everAll、once、interval、debounce
1.ever

        ever 会在指定的 Rx 变量每次变化时调用回调函数。
  1. class Controller extends GetxController {
  2.   final count1 = 0.obs;
  3.   final count2 = 0.obs;
  4.   // sum 的值为 count1 和 count2 的总和
  5.   int get sum => count1.value + count2.value;
  6.   // 增加 count1 的值
  7.   void incrementCount1() {
  8.     count1.value++;
  9.   }
  10.   @override
  11.   void onInit() {
  12.     ever(count2, (_) {
  13.       debugPrint("Count changed: $count2");
  14.     });
  15.     super.onInit();
  16.   }
  17.   // 增加 count2 的值
  18.   void incrementCount2() {
  19.     count2.value++;
  20.   }
  21. }
复制代码
2.everAll

        everAll 会在多个指定的 Rx 变量中的恣意一个变化时调用回调函数。
  1. class MyController extends GetxController {
  2.   var count1 = 0.obs;
  3.   var count2 = 0.obs;
  4.   @override
  5.   void onInit() {
  6.     everAll([count1, count2], (_) {
  7.       print("One of the counts changed: count1 = $count1, count2 = $count2");
  8.     });
  9.     super.onInit();
  10.   }
  11.   void incrementCount1() {
  12.     count1++;
  13.   }
  14.   void incrementCount2() {
  15.     count2++;
  16.   }
  17. }
复制代码
3.once

        once 只会在指定的 Rx 变量第一次变化时调用回调函数。
  1. class MyController extends GetxController {
  2.   var count = 0.obs;
  3.   @override
  4.   void onInit() {
  5.     once(count, (_) {
  6.       print("Count changed for the first time: $count");
  7.     });
  8.     super.onInit();
  9.   }
  10.   void increment() {
  11.     count++;
  12.   }
  13. }
复制代码
4.interval

        interval 会在指定的 Rx 变量变化时调用回调函数,但在指定时间内只会调用一次,实用于减少频仍更新的场景。
  1. class MyController extends GetxController {
  2.   var count = 0.obs;
  3.   @override
  4.   void onInit() {
  5.     interval(count, (_) {
  6.       print("Count changed (with interval): $count");
  7.     }, time: Duration(seconds: 1));
  8.     super.onInit();
  9.   }
  10.   void increment() {
  11.     count++;
  12.   }
  13. }
复制代码
5.debounce

        debounce 会在指定的 Rx 变量变化后的一段时间内没有再次变化时调用回调函数,实用于处置惩罚用户输入等场景。
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. class MyController extends GetxController {
  4.   var count1 = 0.obs;
  5.   var count2 = 0.obs;
  6.   @override
  7.   void onInit() {
  8.     super.onInit();
  9.     // 每次 count1 变化时都会执行回调
  10.     ever(count1, (_) {
  11.       print("Count1 changed: $count1");
  12.     });
  13.     // 任意一个 count1 或 count2 变化时都会执行回调
  14.     everAll([count1, count2], (_) {
  15.       print("Count1 or Count2 changed: count1 = $count1, count2 = $count2");
  16.     });
  17.     // count1 第一次变化时执行回调
  18.     once(count1, (_) {
  19.       print("Count1 changed for the first time: $count1");
  20.     });
  21.     // count1 变化时每隔1秒执行一次回调
  22.     interval(count1, (_) {
  23.       print("Count1 changed (with interval): $count1");
  24.     }, time: Duration(seconds: 1));
  25.     // count1 变化后1秒内没有再次变化时执行回调
  26.     debounce(count1, (_) {
  27.       print("Count1 changed (debounced): $count1");
  28.     }, time: Duration(seconds: 1));
  29.   }
  30.   void incrementCount1() {
  31.     count1++;
  32.   }
  33.   void incrementCount2() {
  34.     count2++;
  35.   }
  36. }
  37. void main() {
  38.   runApp(MyApp());
  39. }
  40. class MyApp extends StatelessWidget {
  41.   @override
  42.   Widget build(BuildContext context) {
  43.     return GetMaterialApp(
  44.       home: HomeScreen(),
  45.     );
  46.   }
  47. }
  48. class HomeScreen extends StatelessWidget {
  49.   final MyController controller = Get.put(MyController());
  50.   @override
  51.   Widget build(BuildContext context) {
  52.     return Scaffold(
  53.       appBar: AppBar(
  54.         title: Text('GetX Workers Example'),
  55.       ),
  56.       body: Center(
  57.         child: Column(
  58.           mainAxisAlignment: MainAxisAlignment.center,
  59.           children: [
  60.             Obx(() => Text('Count1: ${controller.count1}')),
  61.             Obx(() => Text('Count2: ${controller.count2}')),
  62.             ElevatedButton(
  63.               onPressed: controller.incrementCount1,
  64.               child: Text('Increment Count1'),
  65.             ),
  66.             ElevatedButton(
  67.               onPressed: controller.incrementCount2,
  68.               child: Text('Increment Count2'),
  69.             ),
  70.           ],
  71.         ),
  72.       ),
  73.     );
  74.   }
  75. }
复制代码
6.Workers完整示例

        以下是一个完整示例,展示了如何在 GetX 中利用 Workers。
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. class MyController extends GetxController {
  4.   var count1 = 0.obs;
  5.   var count2 = 0.obs;
  6.   @override
  7.   void onInit() {
  8.     super.onInit();
  9.     // 每次 count1 变化时都会执行回调
  10.     ever(count1, (_) {
  11.       print("Count1 changed: $count1");
  12.     });
  13.     // 任意一个 count1 或 count2 变化时都会执行回调
  14.     everAll([count1, count2], (_) {
  15.       print("Count1 or Count2 changed: count1 = $count1, count2 = $count2");
  16.     });
  17.     // count1 第一次变化时执行回调
  18.     once(count1, (_) {
  19.       print("Count1 changed for the first time: $count1");
  20.     });
  21.     // count1 变化时每隔1秒执行一次回调
  22.     interval(count1, (_) {
  23.       print("Count1 changed (with interval): $count1");
  24.     }, time: Duration(seconds: 1));
  25.     // count1 变化后1秒内没有再次变化时执行回调
  26.     debounce(count1, (_) {
  27.       print("Count1 changed (debounced): $count1");
  28.     }, time: Duration(seconds: 1));
  29.   }
  30.   void incrementCount1() {
  31.     count1++;
  32.   }
  33.   void incrementCount2() {
  34.     count2++;
  35.   }
  36. }
  37. void main() {
  38.   runApp(MyApp());
  39. }
  40. class MyApp extends StatelessWidget {
  41.   @override
  42.   Widget build(BuildContext context) {
  43.     return GetMaterialApp(
  44.       home: HomeScreen(),
  45.     );
  46.   }
  47. }
  48. class HomeScreen extends StatelessWidget {
  49.   final MyController controller = Get.put(MyController());
  50.   @override
  51.   Widget build(BuildContext context) {
  52.     return Scaffold(
  53.       appBar: AppBar(
  54.         title: Text('GetX Workers Example'),
  55.       ),
  56.       body: Center(
  57.         child: Column(
  58.           mainAxisAlignment: MainAxisAlignment.center,
  59.           children: [
  60.             Obx(() => Text('Count1: ${controller.count1}')),
  61.             Obx(() => Text('Count2: ${controller.count2}')),
  62.             ElevatedButton(
  63.               onPressed: controller.incrementCount1,
  64.               child: Text('Increment Count1'),
  65.             ),
  66.             ElevatedButton(
  67.               onPressed: controller.incrementCount2,
  68.               child: Text('Increment Count2'),
  69.             ),
  70.           ],
  71.         ),
  72.       ),
  73.     );
  74.   }
  75. }
复制代码
5.唯一的ID

        假如你想用GetBuilder完善一个widget的更新控件,你可以给它们分配唯一的ID。
   GetBuilder<Controller>(
  id: 'text', //这里
  init: Controller(), // 每个控制器只用一次
  builder: (_) => Text(
    '${Get.find<Controller>().counter}', //here
  ),
),
          并更新它:
   update(['text']);
  
        GetX会自动举行重修,并且只重修利用被更改的变量的小组件,假如您将一个变量更改为与之前相同的变量,并且不意味着状态的更改,GetX不会重修小组件以节流内存和CPU周期(界面上正在表现3,而您再次将变量更改为3。在大多数状态管理器中,这将导致一个新的重修,但在GetX中,假如究竟上他的状态已经改变,那么widget将只被再次重修)












免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表