GetX 状态管理学习(初学通俗版)¶
核心目标:不用复杂概念,不用记一堆API,解决原生
setState的痛点,看完就能上手写计数器、全局状态共享、跨页面传值,听完就懂、上手就会。
一、先搞懂:原生状态有什么麻烦?¶
你之前写页面状态用的原生写法是这样的:
int count = 0;
// 修改变量必须调用setState,否则UI不刷新
onPressed: (){
setState((){
count++;
});
}
核心痛点(初学最直观的麻烦):
1. 只能在当前页面用,跨页面传值、共享状态非常麻烦(比如登录状态、购物车数量要在多个页面显示)
2. 业务逻辑和UI代码混在一起,页面写多了乱七八糟,维护困难
3. 每次改状态都要手动写setState,少写就不刷新,写多了重复代码
4. 控制器/工具类里没法直接改页面状态,必须传回调或者上下文
二、GetX 状态管理核心一句话¶
不用 setState!不用 Provider 那一堆复杂的上下文注入,三步就能实现响应式更新,页面、控制器随便改状态,自动刷新UI。
唯一前提(和路由一样):
已经把 MaterialApp 换成 GetMaterialApp(路由已经换过的话直接用,不用再改)。
三、3个核心概念(大白话解释,不用记原理)¶
不用管什么"响应式编程"、"单向数据流"这些虚的,就记住3个东西:
1. .obs(响应式变量):就是你要监听的变量,给普通变量后缀加个.obs,它一变就会自动通知UI刷新
2. GetxController(控制器):专门放状态变量和业务逻辑的类,和UI页面分离,逻辑可以复用,多个页面可以共用同一个控制器
3. Obx/GetBuilder(监听组件):UI里用它把要显示变量的地方包起来,只要变量变了,这块UI自动刷新,不用手动调用任何方法
四、2种最常用写法(必背,对应不同场景)¶
写法1:简单版(GetBuilder,新手首选,不用.obs,手动更新)¶
适合场景:简单页面状态、不需要自动实时更新的场景,写法最像原生,零学习成本。
3步直接套:¶
步骤1:写控制器(放状态和逻辑)
// 新建counter_controller.dart
import 'package:get/get.dart';
class CounterController extends GetxController {
// 普通变量,不用加.obs
int count = 0;
// 写修改状态的方法
void increment() {
count++;
// 手动通知UI刷新(就这一句,代替setState)
update();
}
}
步骤2:页面里注册控制器
// 在页面的build方法最顶部注册,注册一次全局可用
final CounterController controller = Get.put(CounterController());
步骤3:UI里用GetBuilder包起来,显示/修改状态
// 显示变量:用controller.count直接拿
GetBuilder<CounterController>(
builder: (controller) => Text("当前计数:${controller.count}"),
)
// 修改状态:直接调用控制器方法,不用setState
ElevatedButton(
onPressed: () => controller.increment(),
child: Text("点我加1"),
)
写法2:响应式版(Obx + .obs,自动更新,更省事)¶
适合场景:需要实时自动更新的场景(比如实时显示播放进度、聊天消息、倒计时),不用手动调用update(),改了变量自动刷新。
3步直接套:¶
步骤1:写控制器(响应式变量加.obs)
// 新建counter_controller.dart
import 'package:get/get.dart';
class CounterController extends GetxController {
// 给变量后缀加.obs,变成响应式变量
RxInt count = 0.obs;
// 其他类型示例:
// RxBool isLogin = false.obs;
// RxString userName = "".obs;
// RxList<String> list = <String>[].obs;
// 修改方法,不用调用update()
void increment() {
count++; // 直接改就行,自动通知UI刷新
}
}
步骤2:页面注册控制器(和上面一样)
final CounterController controller = Get.put(CounterController());
步骤3:UI里用Obx包起来,自动刷新
// 显示变量:要用.value取响应式变量的值
Obx(() => Text("当前计数:${controller.count.value}"))
// 修改状态(和上面一样)
ElevatedButton(
onPressed: () => controller.increment(),
child: Text("点我加1"),
)
五、关键区别(最简单记忆)¶
| 写法 | 要不要.obs | 要不要手动update() | 适用场景 |
|---|---|---|---|
| GetBuilder | 不用 | 要 | 简单页面、不需要实时更新 |
| Obx | 要 | 不用 | 实时更新、复杂状态 |
初学建议:先练GetBuilder,写法和原生最像,几乎零学习成本,能搞定80%的场景。
六、全局状态共享(最实用功能,原生根本比不了)¶
GetX最大的优势:同一个控制器,多个页面可以共用,一处修改,所有地方自动更新!
比如做全局登录状态:
1. 写一个UserController,里面放isLogin、userName这些全局状态
2. 在main.dart里提前注册:Get.put(UserController())
3. 任何页面、任何控制器里,只要写final UserController userController = Get.find();就能拿到这个全局控制器
4. 登录页改了userController.isLogin = true.obs,所有用到这个变量的页面(首页、我的页面)自动更新状态,不用传值、不用通知、不用回调!
示例代码(全局登录状态):
// 1. 全局控制器
class UserController extends GetxController {
RxBool isLogin = false.obs;
RxString userName = "未登录".obs;
void login(String name) {
userName.value = name;
isLogin.value = true;
}
void logout() {
userName.value = "未登录";
isLogin.value = false;
}
}
// 2. main.dart里提前注册
void main() {
Get.put(UserController()); // 全局注册一次
runApp(GetMaterialApp(home: LoginPage()));
}
// 3. 登录页调用
final UserController userController = Get.find();
userController.login("张三"); // 登录,修改全局状态
// 4. 我的页面直接用
Obx(() => Text("当前用户:${userController.userName.value}"))
// 自动显示"张三",不用传任何参数!
七、原生 vs GetX 状态管理对比¶
原生写法(麻烦)
// 页面内定义变量
int count = 0;
// 必须写setState,只能当前页面用
ElevatedButton(
onPressed: (){
setState((){
count++;
});
},
child: Text("${count}"),
)
// 跨页面共享?要写一堆传值、回调、通知,新手根本搞不定
GetX写法(简单)
// 控制器里定义,全应用通用
var count = 0.obs;
// 改状态不用setState,任何地方都能改
onPressed: () => count++,
// UI自动刷新,不用任何额外代码
Obx(() => Text("${count.value}"))
八、和你之前的项目结合(直接套用)¶
结合你之前的Vexfy音乐播放器项目,直接套用:
1. 写PlayerController继承GetxController,里面放playStatus(播放/暂停)、currentSong(当前歌曲)、progress(播放进度)这些状态
2. 页面里注册控制器,播放页、列表页、底部播放栏都用Get.find()拿到同一个控制器
3. 播放页点暂停,修改playStatus,底部播放栏自动刷新显示暂停状态,不用任何传值
4. 列表页点歌曲,修改currentSong,播放页自动更新歌曲信息,完全不用跨页面传参
补充说明(初学必看)¶
- 前提:已经在
pubspec.yaml引入GetX依赖,已经把MaterialApp换成GetMaterialApp - 控制器注册一次就够,不用重复注册,
Get.put()注册,Get.find()获取,全应用通用 - 不用记复杂的API,先练熟上面2种基础写法,就能搞定90%的业务场景,什么永久控制器、绑定、依赖注入这些进阶功能以后再学
- 状态更新是局部刷新,只有包在Obx/GetBuilder里的UI会更新,比setState全页面刷新性能好很多