flutter GetX 详解

GetX 是 Flutter 生态中非常流行的轻量级、高性能框架,它将状态管理、路由管理、依赖注入三大核心功能整合在一起,同时提供了大量实用工具。


一、GetX 三大核心功能

功能 说明 关键类/方法
状态管理 响应式编程,自动更新UI GetxController, Obx, GetX, Rx
路由管理 无需 BuildContext 的导航 Get.to(), Get.back(), Get.offAll()
依赖注入 自动管理 Controller 生命周期 Get.put(), Get.find(), Bindings

二、状态管理详解

1. 响应式状态(Reactive State)

GetX 使用 Rx 类型实现响应式编程,当数据变化时自动刷新 UI。

复制代码
import 'package:get/get.dart';

class CounterController extends GetxController {
  // 定义响应式变量
  var count = 0.obs;           // int 的响应式版本
  var name = 'Flutter'.obs;    // String 的响应式版本
  var items = <String>[].obs;  // List 的响应式版本
  
  void increment() => count++;
  void changeName(String newName) => name.value = newName;
}

2. 三种监听方式

方式一:Obx(最轻量,推荐)
复制代码
class HomePage extends StatelessWidget {
  final controller = Get.put(CounterController());
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        // Obx 只监听其内部使用的 Rx 变量
        child: Obx(() => Text(
          '点击次数: ${controller.count.value}',
          style: TextStyle(fontSize: 24),
        )),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}
方式二:GetX(监听整个 Controller)
复制代码
GetX<CounterController>(
  builder: (controller) {
    return Text('点击次数: ${controller.count.value}');
  },
)
方式三:GetBuilder(手动更新,性能最高)
复制代码
class CounterController extends GetxController {
  int count = 0;
  
  void increment() {
    count++;
    update(); // 手动触发更新,类似 notifyListeners()
  }
}

// UI 中使用
GetBuilder<CounterController>(
  builder: (controller) {
    return Text('点击次数: ${controller.count}');
  },
)

3. Workers(监听器)

Workers 用于监听 Rx 变量的变化并执行副作用:

复制代码
class UserController extends GetxController {
  final name = ''.obs;
  final age = 0.obs;
  
  @override
  void onInit() {
    super.onInit();
    
    // 每次变化都执行
    ever(name, (value) => print('名字变为: $value'));
    
    // 只执行一次
    once(age, (value) => print('年龄第一次变化: $value'));
    
    // 防抖(停止输入 1 秒后执行)
    debounce(name, (value) => print('搜索: $value'), time: Duration(seconds: 1));
    
    // 节流(每 2 秒最多执行一次)
    interval(count, (value) => print('计数: $value'), time: Duration(seconds: 2));
  }
}

三、路由管理

GetX 路由完全脱离 BuildContext,代码更简洁。

基础导航

复制代码
// 跳转到新页面
Get.to(HomePage());

// 返回上一页
Get.back();

// 替换当前页面(无法返回)
Get.off(HomePage());

// 清除所有页面并跳转(如登录后进入首页)
Get.offAll(HomePage());

// 跳转到命名路由
Get.toNamed('/home');

// 带参数跳转
Get.toNamed('/profile', arguments: {'id': 123, 'name': '张三'});

路由配置

复制代码
void main() {
  runApp(GetMaterialApp(
    initialRoute: '/',
    getPages: [
      GetPage(name: '/', page: () => SplashPage()),
      GetPage(name: '/home', page: () => HomePage()),
      GetPage(
        name: '/profile/:id',
        page: () => ProfilePage(),
        // 中间件(如登录验证)
        middlewares: [AuthMiddleware()],
        // 转场动画
        transition: Transition.cupertino,
      ),
    ],
  ));
}

接收参数

复制代码
class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 获取路由参数
    final id = Get.parameters['id'];
    final args = Get.arguments;
    
    return Scaffold(
      appBar: AppBar(title: Text('用户 $id')),
    );
  }
}

四、依赖注入(Bindings)

Bindings 用于将 Controller 与页面绑定,自动管理生命周期。

1. 基础使用

复制代码
class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
    Get.lazyPut(() => UserController());
  }
}

// 路由中绑定
GetPage(
  name: '/home',
  page: () => HomePage(),
  binding: HomeBinding(),
)

2. 依赖注入方式对比

复制代码
// 立即注入(应用启动时创建)
Get.put(Controller());

// 懒加载(第一次使用时创建,推荐)
Get.lazyPut(() => Controller());

// 异步注入(如需要网络请求初始化)
Get.putAsync(() async => await SharedPrefsController.init());

// 创建新实例(每次调用都新建)
Get.create(() => Controller());

3. 查找依赖

dart

复制代码
// 在任意位置获取 Controller
final controller = Get.find<HomeController>();

// 删除依赖(释放资源)
Get.delete<HomeController>();

五、Controller 生命周期

复制代码
class MyController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    // 初始化数据、监听 Workers
  }
  
  @override
  void onReady() {
    super.onReady();
    // 首次渲染完成后调用(类似 initState 之后)
  }
  
  @override
  void onClose() {
    // 页面销毁时调用,释放资源、取消订阅
    super.onClose();
  }
}

六、实用工具

1. Snackbar(提示条)

复制代码
Get.snackbar(
  '操作成功',
  '数据已保存',
  snackPosition: SnackPosition.BOTTOM,
  backgroundColor: Colors.green,
  colorText: Colors.white,
  duration: Duration(seconds: 2),
);

2. Dialog(对话框)

复制代码
Get.defaultDialog(
  title: '确认删除',
  middleText: '此操作不可撤销',
  textConfirm: '删除',
  textCancel: '取消',
  confirmTextColor: Colors.white,
  onConfirm: () => Get.back(),
);

// 自定义 Dialog
Get.dialog(AlertDialog(...));

3. BottomSheet(底部弹

复制代码
Get.bottomSheet(
  Container(
    height: 200,
    color: Colors.white,
    child: Center(child: Text('底部内容')),
  ),
);

4. 主题切换

复制代码
// 切换深色/浅色模式
Get.changeTheme(Get.isDarkMode ? ThemeData.light() : ThemeData.dark());

// 监听系统主题
Get.changeThemeMode(ThemeMode.system);

5. 国际化(i18n)

复制代码
class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
    'zh_CN': {
      'hello': '你好',
      'welcome': '欢迎 @name',
    },
    'en_US': {
      'hello': 'Hello',
      'welcome': 'Welcome @name',
    },
  };
}

// 使用
Text('hello'.tr);                    // 你好
Text('welcome'.trParams({'name': '张三'})); // 欢迎 张三

七、完整实战示例

复制代码
// main.dart
void main() {
  runApp(GetMaterialApp(
    title: 'GetX Demo',
    initialRoute: '/',
    getPages: [
      GetPage(name: '/', page: () => LoginPage()),
      GetPage(
        name: '/home',
        page: () => HomePage(),
        binding: HomeBinding(),
      ),
    ],
  ));
}

// controllers/home_controller.dart
class HomeController extends GetxController {
  final tasks = <Task>[].obs;
  final isLoading = false.obs;
  
  @override
  void onInit() {
    fetchTasks();
    super.onInit();
  }
  
  void fetchTasks() async {
    isLoading.value = true;
    await Future.delayed(Duration(seconds: 1));
    tasks.addAll([
      Task(title: '学习 GetX', done: false),
      Task(title: '完成项目', done: false),
    ]);
    isLoading.value = false;
  }
  
  void toggleTask(int index) {
    tasks[index].done = !tasks[index].done;
    tasks.refresh(); // 刷新列表
  }
}

// bindings/home_binding.dart
class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
  }
}

// pages/home_page.dart
class HomePage extends StatelessWidget {
  final controller = Get.find<HomeController>();
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('任务列表')),
      body: Obx(() {
        if (controller.isLoading.value) {
          return Center(child: CircularProgressIndicator());
        }
        return ListView.builder(
          itemCount: controller.tasks.length,
          itemBuilder: (context, index) {
            final task = controller.tasks[index];
            return ListTile(
              title: Text(
                task.title,
                style: TextStyle(
                  decoration: task.done ? TextDecoration.lineThrough : null,
                ),
              ),
              trailing: Checkbox(
                value: task.done,
                onChanged: (_) => controller.toggleTask(index),
              ),
            );
          },
        );
      }),
    );
  }
}

八、GetX vs 其他方案

特性 GetX Provider Riverpod BLoC
学习曲线 ⭐ 低
代码量 极少 较少 较少 较多
性能
路由管理 ✅ 内置 ❌ 需额外库 ❌ 需额外库 ❌ 需额外库
依赖注入 ✅ 内置 ❌ 需额外库 ✅ 内置 ❌ 需额外库
社区活跃度
官方推荐 非官方 非官方 非官方 非官方

九、注意事项

  1. 避免在 build 中调用 Get.put():应在页面顶部或 Binding 中注入

  2. Obx 嵌套问题:不要在 Obx 内部再创建 Obx 监听同一个 Controller,会导致重复监听

  3. Rx 集合的更新 :修改 List/Map 后需调用 .refresh().value = ...

  4. GetMaterialApp :使用 GetX 路由必须用 GetMaterialApp 替代 MaterialApp

  5. 与原生 Navigator 混用:尽量避免,可能导致路由栈混乱


GetX 的最大优势在于**"一站式"解决方案**------用一套框架同时解决状态、路由、依赖三大问题,代码简洁、学习成本低,非常适合中小型项目快速开发。对于大型项目,也可以只使用其中某个模块(如只用状态管理,路由仍用 Navigator 2.0)。

相关推荐
MyFreeIT2 小时前
Android Manual
android
hai_android3 小时前
AIDL 实现 IPC 进程间通信
android·android studio
AFinalStone5 小时前
Android 7系统无障碍服务(五)AccessibilityNodeInfo 的构建与查询
android·无障碍服务
坚果的博客5 小时前
Flutter OHOS 环境搭建实战:oh-3.44.9-dev 从 0 到 1 完整记录
flutter·华为·harmonyos
今天要早睡_5 小时前
C++ 核心语法速过:命名空间、引用、函数重载与 nullptr 深度解析
android·java·c++
啦啦啦~~~2226 小时前
PC端+安卓端阅读器推荐!开源本地小说阅读器软件,
android·论文阅读·windows·开源软件·福昕阅读器
Crazy_MT7 小时前
Android Studio 运行 Flutter iOS 真机白屏,但 Xcode 和命令行正常的排查记录
flutter·android studio
我命由我123457 小时前
Android Jetpack Compose 开发问题:Unresolved reference ‘Icons‘.
android·java-ee·kotlin·android studio·android jetpack·android-studio·android runtime
爱笑鱼7 小时前
Android 系统启动机制(六):Zygote 创建 App 为什么走 Socket?哪些是源码事实,哪些是架构解释?
android·linux