mcpField
G
GetX State Management Patterns

GetX State Management Patterns

github.com/kaakati开发1084 次安装39 周前更新
代码仓库

关于 GetX State Management Patterns

GetX State Management Patterns 是面向使用 GetX 的 Flutter 开发者的编码技能,涵盖响应式状态、依赖注入、导航和控制器生命周期,并说明如何避免将业务逻辑放入控制器。

主要功能

  1. 01响应式变量与组件
  2. 02使用 Bindings 进行依赖注入
  3. 03路由导航与参数传递
  4. 04控制器生命周期指引
  5. 05Snackbar 与对话框
  6. 06状态管理最佳实践

适用场景

  1. 01在 Flutter 组件中显示响应式数据
  2. 02通过 Bindings 注册控制器和服务
  3. 03在命名路由或直接路由间导航
  4. 04将业务逻辑放在控制器之外

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kaakati/rails-enterprise-dev --skill getx-state-management-patterns

安装后在 Claude Code 中输入/getx-state-management-patterns确认已加载。

详细介绍

GetX 状态管理模式

响应式状态管理

响应式变量
class UserController extends GetxController {
  // Simple reactive variable
  final count = 0.obs;
  
  // Complex reactive variable
  final user = Rx<User?>(null);
  
  // Reactive list
  final users = <User>[].obs;
  
  // Reactive map
  final settings = <String, dynamic>{}.obs;
  
  // Getters (recommended)
  int get countValue => count.value;
  User? get currentUser => user.value;
}
响应式组件
// Option 1: Obx (lightweight)
Obx(() => Text(controller.count.toString()))

// Option 2: GetX (with dependency injection)
GetX<UserController>(
  builder: (controller) => Text(controller.user?.name ?? 'Loading...'),
)

// Option 3: GetBuilder (no reactive variables needed)
GetBuilder<UserController>(
  builder: (controller) => Text(controller.userName),
)

依赖注入

注册方法
// Immediate instance
Get.put(UserController());

// Lazy instance (created when first used)
Get.lazyPut(() => UserController());

// Singleton (persists across routes)
Get.putAsync(() => StorageService().init());

// Fenix (recreates when route is accessed again)
Get.lazyPut(() => UserController(), fenix: true);
Bindings 模式
class UserBinding extends Bindings {
  @override
  void dependencies() {
    // Data sources
    Get.lazyPut(() => UserProvider(Get.find()));
    Get.lazyPut(() => UserLocalSource(Get.find()));
    
    // Repository
    Get.lazyPut<UserRepository>(
      () => UserRepositoryImpl(Get.find(), Get.find()),
    );
    
    // Use cases
    Get.lazyPut(() => GetUser(Get.find()));
    
    // Controller
    Get.lazyPut(() => UserController(getUserUseCase: Get.find()));
  }
}

导航

基本导航
// Navigate to route
Get.to(() => ProfilePage());

// Navigate with name
Get.toNamed('/profile');

// Navigate and remove previous
Get.off(() => LoginPage());

// Navigate and remove all previous
Get.offAll(() => HomePage());

// Go back
Get.back();

// Go back with result
Get.back(result: user);
带参数导航
// Send arguments
Get.toNamed('/profile', arguments: {'id': '123'});

// Receive arguments
final args = Get.arguments as Map<String, dynamic>;
final id = args['id'];
路由配置
class AppRoutes {
  static const initial = '/splash';
  
  static final routes = [
    GetPage(
      name: '/splash',
      page: () => SplashPage(),
      binding: SplashBinding(),
    ),
    GetPage(
      name: '/login',
      page: () => LoginPage(),
      binding: AuthBinding(),
      transition: Transition.fadeIn,
    ),
    GetPage(
      name: '/home',
      page: () => HomePage(),
      binding: HomeBinding(),
      middlewares: [AuthMiddleware()],
    ),
  ];
}

控制器生命周期

class UserController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    // Called immediately after controller is allocated
    loadUser();
  }
  
  @override
  void onReady() {
    super.onReady();
    // Called after widget is rendered
    analytics.logScreenView();
  }
  
  @override
  void onClose() {
    // Clean up resources
    _subscription.cancel();
    super.onClose();
  }
}

Snackbars 和对话框

// Snackbar
Get.snackbar(
  'Success',
  'User created successfully',
  snackPosition: SnackPosition.BOTTOM,
  backgroundColor: Colors.green,
);

// Dialog
Get.dialog(
  AlertDialog(
    title: Text('Confirm'),
    content: Text('Are you sure?'),
    actions: [
      TextButton(
        onPressed: () => Get.back(),
        child: Text('Cancel'),
      ),
      TextButton(
        onPressed: () {
          deleteUser();
          Get.back();
        },
        child: Text('Delete'),
      ),
    ],
  ),
);

// Bottom sheet
Get.bottomSheet(
  Container(
    child: Column(
      children: [
        ListTile(
          title: Text('Option 1'),
          onTap: () => Get.back(result: 1),
        ),
      ],
    ),
  ),
);

最佳实践

✅ 应当
  • 使用 bindings 进行依赖注入
  • 使用私有响应式变量,并提供公共 getter
  • 在 onClose() 中清理资源
  • 使用有意义的控制器名称(例如,UserController,而不是 Controller1)
  • 将业务逻辑放在用例中,而不是控制器中
❌ 不应
  • 不要直接在组件中创建控制器
  • 不要将业务逻辑放在控制器中
  • 不要忘记释放流和订阅
  • 不要过度使用全局状态
  • 不要创建循环依赖

应避免的反模式

// ❌ BAD: Business logic in controller
class UserController extends GetxController {
  Future<void> createUser(String name, String email) async {
    // Direct API call in controller
    final response = await http.post(...);
    // Business logic in controller
    if (response.statusCode == 201) {
      user.value = User.fromJson(response.body);
    }
  }
}

// ✅ GOOD: Delegate to use case
class UserController extends GetxController {
  final CreateUser createUserUseCase;
  
  Future<void> createUser(String name, String email) async {
    final result = await createUserUseCase(name, email);
    result.fold(
      (failure) => _handleError(failure),
      (user) => user.value = user,
    );
  }
}

评论

支持 Markdown