GetX功能介绍

  • 依赖注入
    • GetX是通过依赖注入的方式,存储相应的XxxGetxController;已经脱离了InheritedWidget那一套玩法,自己手动去管理这些实例,使用场景被大大拓展
    • 简单的思路,却能产生深远的影响:优雅的跨页面功能便是基于这种设计而实现的、获取实例无需BuildContext、GetBuilder自动化的处理及其减少了入参等等
  • 跨页面交互
    • 这绝对是GetX的一个优点!对于复杂的生产环境,跨页面交互的场景,实在太常见了,GetX的跨页面交互,几乎和fish_redux一样简单。
  • 路由管理
    • 是的,getx内部实现了路由管理,而且用起来,那叫一个简单!bloc没实现路由管理,这让我不得不去找一个star量高的路由管理框架,就选择了fluro,但是让我不得不说,这个fluro用起来真的叫一个折磨人,每次新建一个页面,最让我抗拒的就是去写fluro路由代码,横跨几个文件来回写,真是肝疼
    • GetX实现了动态路由传参,也就是说直接在命名路由上拼参数,然后能拿到这些拼在路由上的参数,也就是说用flutter写H5,直接能通过Url传值(fluro也能做到)
  • 实现了全局BuildContext
  • 国际化,主题实现。

使用

引用

  1. # getx 状态管理框架 https://pub.flutter-io.cn/packages/get
  2. # 非空安全最后一个版本(flutter 2.0之前版本)
  3. get: ^3.26.0
  4. # 空安全版本 最新版本请查看 https://pub.flutter-io.cn/packages/get
  5. get: ^4.3.8
  • Github:jonataslaw/getx
  • Pub:get

    程序入口

  • 只需要将MaterialApp改成GetMaterialApp即可 ```dart void main() { runApp(MyApp()); }

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( home: CounterGetPage(), ); } }

  1. <a name="gWQW7"></a>
  2. ### 插件
  3. **此外,为了进一步提高您的生产效率,我们还为您准备了一些插件**
  4. - **getx_template**:一键生成每个页面必需的文件夹、文件、模板代码等等
  5. - [Android Studio/Intellij插件](https://plugins.jetbrains.com/plugin/15919-getx)
  6. - **GetX Snippets**:输入少量字母,自动提示选择后,可生成常用的模板代码
  7. - [Android Studio/Intellij扩展](https://plugins.jetbrains.com/plugin/14975-getx-snippets)
  8. - [VSCode扩展](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)
  9. <a name="Caanv"></a>
  10. ### 计数器程序
  11. > 实现一个计数器程序来看下GetX如何将逻辑层和界面层解耦。
  12. 1. 创建一个 get_x_demo 的 flutter 项目。
  13. 1. 安装 getx。
  14. ```shell
  15. flutter pub add get
  1. 利用插件生成文件。

image.png

  1. 修改主入口 ```dart import ‘package:flutter/material.dart’; import ‘package:get/get.dart’;

import ‘counter_get/view.dart’;

void main() { runApp(const MyApp()); }

class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key);

@override Widget build(BuildContext context) { return GetMaterialApp( title: ‘Flutter Demo’, theme: ThemeData(primarySwatch: Colors.blue), home: const CounterGetPage(), ); } }

  1. 5. 编写逻辑层代码
  2. ```dart
  3. import 'package:get/get.dart';
  4. class CounterGetLogic extends GetxController {
  5. var count = 0.obs;
  6. /// 自增
  7. void increase() => ++count;
  8. /// 自减
  9. void remove() => --count;
  10. }
  1. 编写视图层代码 ```dart import ‘package:flutter/material.dart’; import ‘package:get/get.dart’;

import ‘logic.dart’;

class CounterGetPage extends StatelessWidget { const CounterGetPage({Key? key}) : super(key: key);

@override Widget build(BuildContext context) { final logic = Get.put(CounterGetLogic()); return Scaffold( appBar: AppBar( title: const Text(“GetX Count”), ), body: Center( child: Obx(() { return Text( logic.count.value.toString(), style: const TextStyle(fontSize: 24), ); }), ), floatingActionButton: Column( mainAxisSize: MainAxisSize.min, children: [ FloatingActionButton( heroTag: “add”, onPressed: logic.increase, child: const Icon(Icons.add), ), const SizedBox(height: 10), FloatingActionButton( heroTag: “sub”, onPressed: logic.remove, backgroundColor: Colors.red, child: const Icon(Icons.remove), ) ], ), ); } }

  1. 7. 运行程序
  2. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/179485/1632280372394-d373840d-424f-4fb6-b2f6-a3f88cdef320.png#clientId=ud52e82e4-288e-4&from=paste&height=697&id=ue03bf6bc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1394&originWidth=822&originalType=binary&ratio=1&size=67366&status=done&style=none&taskId=u9968abd5-1180-4fa6-9e69-20d4b20b6fc&width=411)
  3. <a name="uBWp1"></a>
  4. ## 状态管理
  5. <a name="L6Nsl"></a>
  6. ### 响应式状态管理
  7. > 上面的实例中,我们看到两个关键字「obs」和「obx」,配合使用即可。
  8. <a name="XC8wi"></a>
  9. #### 基本数据类型
  10. > 定义一个需要状态管理的变量。obs是响应式状态管理,自动完成数据更新。
  11. Obx()方法刷新的条件
  12. - 只有当响应式变量的值发生变化时,才会会执行刷新操作,当某个变量初始值为:“test”,再赋值为:“test”,并不会执行刷新操作
  13. - 当你定义了一个响应式变量,该响应式变量改变时,包裹该响应式变量的Obx()方法才会执行刷新操作,其它的未包裹该响应式变量的Obx()方法并不会执行刷新操作。
  14. <a name="qSEuS"></a>
  15. #### 基于类的使用
  16. ```dart
  17. import 'package:get/get.dart';
  18. import 'package:get_x_demo/user_obs/user.dart';
  19. import 'dart:math';
  20. class UserObsLogic extends GetxController {
  21. final _names = ["JsonYe", "LiuLi", "Luna", "Tomer"];
  22. final user = User().obs;
  23. @override
  24. void onInit() {
  25. super.onInit();
  26. updateUser();
  27. }
  28. void updateUser() {
  29. User _user = User(
  30. name: _names[Random().nextInt(3)],
  31. age: 30 + Random().nextInt(50),
  32. sex: Random().nextBool());
  33. user.update((val) {
  34. val?.name = _user.name;
  35. val?.age = _user.age;
  36. val?.sex = _user.sex;
  37. });
  38. }
  39. }
  40. class User {
  41. String? name;
  42. int? age;
  43. bool? sex;
  44. User({this.name, this.age, this.sex});
  45. }
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'logic.dart';
  4. class UserObsPage extends StatelessWidget {
  5. const UserObsPage({Key? key}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. final logic = Get.put(UserObsLogic());
  9. return Scaffold(
  10. appBar: AppBar(
  11. title: const Text("Object obs"),
  12. ),
  13. body: Center(
  14. child: Obx(() {
  15. return DefaultTextStyle(
  16. style: const TextStyle(color: Colors.black, fontSize: 30),
  17. child: Column(
  18. mainAxisSize: MainAxisSize.min,
  19. children: [
  20. Text("${logic.user.value.name}"),
  21. Text("${logic.user.value.age}"),
  22. Text("${logic.user().sex}"),
  23. ],
  24. ),
  25. );
  26. }),
  27. ),
  28. floatingActionButton: FloatingActionButton(
  29. onPressed: logic.updateUser,
  30. child: const Icon(Icons.sync),
  31. ),
  32. );
  33. }
  34. }

简单状态管理

通过GetBuilder组件构建,update()方法手动更新。

  1. import 'dart:math';
  2. import 'package:get/get.dart';
  3. class BasicGetLogic extends GetxController {
  4. final _names = ["JsonYe", "LiuLi", "Luna", "Tomer"];
  5. String? name;
  6. int? age;
  7. bool? sex;
  8. @override
  9. void onInit() {
  10. super.onInit();
  11. updateUser();
  12. }
  13. void updateUser() {
  14. name = _names[Random().nextInt(3)];
  15. age = 30 + Random().nextInt(50);
  16. sex = Random().nextBool();
  17. update();
  18. }
  19. }
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'logic.dart';
  4. class BasicGetPage extends StatelessWidget {
  5. const BasicGetPage({Key? key}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. final logic = Get.put(BasicGetLogic());
  9. return Scaffold(
  10. appBar: AppBar(
  11. title: const Text("Basic GetX"),
  12. ),
  13. body: Center(
  14. child: GetBuilder<BasicGetLogic>(
  15. builder: (_logic) {
  16. return DefaultTextStyle(
  17. style: const TextStyle(color: Colors.black, fontSize: 30),
  18. child: Column(
  19. mainAxisSize: MainAxisSize.min,
  20. children: [
  21. Text("${_logic.name}"),
  22. Text("${_logic.age}"),
  23. Text("${_logic.sex}"),
  24. ],
  25. ),
  26. );
  27. },
  28. ),
  29. ),
  30. floatingActionButton: FloatingActionButton(
  31. onPressed: logic.updateUser,
  32. child: const Icon(Icons.sync),
  33. ),
  34. );
  35. }
  36. }

Obx和GetBuilder比较

分析

  • Obx是配合Rx响应式变量使用、GetBuilder是配合update使用:请注意,这完全是俩套定点刷新控件的方案
    • 区别:前者响应式变量变化,Obx自动刷新;后者需要使用update手动调用刷新
  • 每一个响应式变量,都需要生成对应的GetStream,占用资源大于基本数据类型,会对内存造成一定压力
  • GetBuilder内部实际上是对StatefulWidget的封装,所以占用资源极小

    使用场景

  • 一般来说,对于大多数场景都是可以使用响应式变量的

  • 但是,在一个包含了大量对象的List,都使用响应式变量,将生成大量的GetStream,必将对内存造成较大的压力,该情况下,就要考虑使用简单状态管理了
  • 总的来说:推荐GetBuilder和update配合的写法
    • GetBuilder内置回收GetxController的功能,能避免一些无法自动回收GetxController的坑爹问题
      • 使用GetBuilder的自动回收:GetBuilder需要设置assignId: true;或使用插件一键Wrap Widget:GetBuilder(Auto Dispose)
    • 使用Obx,相关变量定义初始化以及实体更新和常规写法不同,会对初次接触该框架的人,造成很大的困扰
    • getx插件现已支持一键Wrap Widget生成GetBuilder,可以一定程度上提升你的开发效率

跨页面交互

页面1

  1. import 'package:get/get.dart';
  2. import 'package:get_x_demo/more_page_get/page_two_get/view.dart';
  3. class PageOneGetLogic extends GetxController {
  4. var count = 0;
  5. void toTwoPage() {
  6. Get.to(const PageTwoGetPage());
  7. }
  8. void increase() {
  9. count = ++count;
  10. update();
  11. }
  12. }
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'logic.dart';
  4. class PageOneGetPage extends StatelessWidget {
  5. const PageOneGetPage({Key? key}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. final logic = Get.put(PageOneGetLogic());
  9. return Scaffold(
  10. backgroundColor: Colors.white,
  11. appBar: AppBar(title: const Text('One Page')),
  12. floatingActionButton: FloatingActionButton(
  13. onPressed: logic.toTwoPage,
  14. child: const Icon(Icons.arrow_forward_outlined),
  15. ),
  16. body: Center(
  17. child: GetBuilder<PageOneGetLogic>(
  18. builder: (logic) {
  19. return Text(
  20. 'Two点击了 ${logic.count} 次',
  21. style: const TextStyle(fontSize: 30.0),
  22. );
  23. },
  24. ),
  25. ),
  26. );
  27. }
  28. }

页面2

  1. import 'package:get/get.dart';
  2. import 'package:get_x_demo/more_page_get/page_one_get/logic.dart';
  3. class PageTwoGetLogic extends GetxController {
  4. final oneLogic = Get.put(PageOneGetLogic());
  5. var count = 0;
  6. @override
  7. void onReady() {
  8. count = oneLogic.count;
  9. update();
  10. super.onReady();
  11. }
  12. void increase() {
  13. oneLogic.increase();
  14. count = oneLogic.count;
  15. update();
  16. }
  17. }
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:get_x_demo/more_page_get/page_one_get/logic.dart';
  4. import 'logic.dart';
  5. class PageTwoGetPage extends StatelessWidget {
  6. const PageTwoGetPage({Key? key}) : super(key: key);
  7. @override
  8. Widget build(BuildContext context) {
  9. final twoLogic = Get.put(PageTwoGetLogic());
  10. return Scaffold(
  11. backgroundColor: Colors.white,
  12. appBar: AppBar(title: const Text('Two Page')),
  13. floatingActionButton: FloatingActionButton(
  14. onPressed: twoLogic.increase,
  15. child: const Icon(Icons.add),
  16. ),
  17. body: Center(
  18. child: GetBuilder<PageTwoGetLogic>(
  19. builder: (logic) {
  20. return Text(
  21. '点击了 ${logic.count} 次',
  22. style: const TextStyle(fontSize: 30.0),
  23. );
  24. },
  25. ),
  26. ),
  27. );
  28. }
  29. }

状态分离

划分三个结构:state(状态层),logic(逻辑层),view(界面层)

State

  1. class CountStateGetState {
  2. late int count;
  3. CountStateGetState() {
  4. count = 0;
  5. }
  6. }

logic

  1. import 'package:get/get.dart';
  2. import 'state.dart';
  3. class CountStateGetLogic extends GetxController {
  4. final CountStateGetState state = CountStateGetState();
  5. void increase() {
  6. state.count = ++state.count;
  7. update();
  8. }
  9. void remove() {
  10. state.count = --state.count;
  11. update();
  12. }
  13. }

view

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'logic.dart';
  4. class CountStateGetPage extends StatelessWidget {
  5. const CountStateGetPage({Key? key}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. final logic = Get.put(CountStateGetLogic());
  9. final state = Get.find<CountStateGetLogic>().state;
  10. return Scaffold(
  11. appBar: AppBar(
  12. title: const Text("Count State Demo"),
  13. ),
  14. body: Center(
  15. child: GetBuilder<CountStateGetLogic>(builder: (_) {
  16. return Text(
  17. state.count.toString(),
  18. style: const TextStyle(fontSize: 30),
  19. );
  20. }),
  21. ),
  22. floatingActionButton: Column(
  23. mainAxisSize: MainAxisSize.min,
  24. children: [
  25. FloatingActionButton(
  26. heroTag: "add",
  27. onPressed: logic.increase,
  28. child: const Icon(Icons.add),
  29. ),
  30. const SizedBox(height: 10),
  31. FloatingActionButton(
  32. heroTag: "sub",
  33. onPressed: logic.remove,
  34. backgroundColor: Colors.red,
  35. child: const Icon(Icons.remove),
  36. )
  37. ],
  38. ),
  39. );
  40. }
  41. }
  • logic只专注于触发事件交互,state只专注数据。

Binding使用

可以统一管理复杂模块的多个GetXController。需要结合getx路由进行使用。

路由

  1. import 'package:get/get.dart';
  2. import 'package:get_x_demo/binding_demo/binding_one_page/binding.dart';
  3. import 'package:get_x_demo/binding_demo/binding_one_page/view.dart';
  4. import 'package:get_x_demo/binding_demo/binding_two_page/binding.dart';
  5. import 'package:get_x_demo/binding_demo/binding_two_page/view.dart';
  6. class RouteConfig {
  7. static const String testOne = "/testOne";
  8. static const String testTwo = "/testTwo";
  9. static final List<GetPage> getPages = [
  10. GetPage(
  11. name: testOne,
  12. page: () => const BindingOnePage(),
  13. binding: BindingOnePageBinding(),
  14. ),
  15. GetPage(
  16. name: testTwo,
  17. page: () => const BindingTwoPage(),
  18. binding: BindingTwoPageBinding(),
  19. ),
  20. ];
  21. }

Page One

  • Logic ```dart import ‘package:get/get.dart’; import ‘package:get_x_demo/binding_demo/route_config.dart’;

class BindingOnePageLogic extends GetxController { void toTwoPage() { Get.toNamed(RouteConfig.testTwo); } }

  1. - Binding
  2. ```dart
  3. import 'package:get/get.dart';
  4. import 'logic.dart';
  5. class BindingOnePageBinding extends Bindings {
  6. @override
  7. void dependencies() {
  8. Get.lazyPut(() => BindingOnePageLogic());
  9. }
  10. }
  • View ```dart import ‘package:flutter/material.dart’; import ‘package:get/get.dart’;

import ‘logic.dart’;

class BindingOnePage extends StatelessWidget { const BindingOnePage({Key? key}) : super(key: key);

@override Widget build(BuildContext context) { final logic = Get.find(); return Scaffold( appBar: AppBar( title: const Text(“Binding Demo”), ), body: Center( child: ElevatedButton( onPressed: logic.toTwoPage, child: const Text(“跳转第二页”), ), ), ); } }

  1. <a name="Wsz84"></a>
  2. ### Page Two
  3. - Logic
  4. ```dart
  5. import 'package:get/get.dart';
  6. class BindingTwoPageLogic extends GetxController {
  7. int count = 0;
  8. void increase() {
  9. count++;
  10. update();
  11. }
  12. void remove() {
  13. count--;
  14. update();
  15. }
  16. }
  • Binding ```dart import ‘package:get/get.dart’;

import ‘logic.dart’;

class BindingTwoPageBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => BindingTwoPageLogic()); } }

  1. - View
  2. ```dart
  3. import 'package:flutter/material.dart';
  4. import 'package:get/get.dart';
  5. import 'logic.dart';
  6. class BindingTwoPage extends StatelessWidget {
  7. const BindingTwoPage({Key? key}) : super(key: key);
  8. @override
  9. Widget build(BuildContext context) {
  10. final logic = Get.find<BindingTwoPageLogic>();
  11. return Scaffold(
  12. appBar: AppBar(
  13. title: const Text("Binding Two Page"),
  14. ),
  15. body: Center(
  16. child: GetBuilder<BindingTwoPageLogic>(
  17. assignId: true,
  18. builder: (logic) {
  19. return Text(
  20. logic.count.toString(),
  21. );
  22. },
  23. ),
  24. ),
  25. floatingActionButton: Column(
  26. mainAxisSize: MainAxisSize.min,
  27. children: [
  28. FloatingActionButton(
  29. heroTag: "add",
  30. onPressed: logic.increase,
  31. child: const Icon(Icons.add),
  32. ),
  33. const SizedBox(height: 10),
  34. FloatingActionButton(
  35. heroTag: "sub",
  36. onPressed: logic.remove,
  37. backgroundColor: Colors.red,
  38. child: const Icon(Icons.remove),
  39. )
  40. ],
  41. ),
  42. );
  43. }
  44. }

转载:Flutter GetX使用—-简洁的魅力!