home / skills / hoangnguyen0403 / agent-skills-standard / getx-state-management

getx-state-management skill

/skills/flutter/getx-state-management

This skill helps you implement reactive GetX state management in Flutter, using controllers, bindings, and Obx for clean MVVM architecture.

npx playbooks add skill hoangnguyen0403/agent-skills-standard --skill getx-state-management

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.0 KB
---
name: Flutter GetX State Management
description: Simple and powerful reactive state management using GetX.
metadata:
  labels: [flutter, state-management, getx, controller, reactive]
  triggers:
    files: ['**_controller.dart', '**/bindings/*.dart']
    keywords:
      [GetxController, Obx, GetBuilder, .obs, Get.put, Get.find, Get.lazyPut]
---

# GetX State Management

## **Priority: P0 (CRITICAL)**

## Structure

```text
lib/app/modules/home/
├── controllers/
│   └── home_controller.dart
├── bindings/
│   └── home_binding.dart
└── views/
    └── home_view.dart
```

## Implementation Guidelines

- **Controllers**: Extend `GetxController`. Store logic and state variables here.
- **Reactivity**:
  - Use `.obs` for observable variables (e.g., `final count = 0.obs;`).
  - Wrap UI in `Obx(() => ...)` to listen for changes.
  - For simple state, use `update()` in controller and `GetBuilder` in UI.
- **Dependency Injection**:
  - **Bindings**: Use `Bindings` class to decouple DI from UI.
  - **Lazy Load**: Prefer `Get.lazyPut(() => Controller())` in Bindings.
  - **Lifecycle**: Let GetX handle disposal. Avoid `permanent: true`.
- **Hooks**: Use `onInit()`, `onReady()`, `onClose()` instead of `initState`/`dispose`.
- **Architecture**: Use `get_cli` for modular MVVM (data, models, modules).

## Anti-Patterns

- **Ctx in Logic**: Pass no `BuildContext` to controllers.
- **Inline DI**: Avoid `Get.put()` in widgets; use Bindings + `Get.find`.
- **Fat Views**: Keep views pure UI; delegate all logic to controller.

## Code Example

```dart
class UserController extends GetxController {
  final name = "User".obs;
  void updateName(String val) => name.value = val;
}

class UserView extends GetView<UserController> {
  @override
  Widget build(ctx) => Scaffold(
    body: Obx(() => Text(controller.name.value)),
    floatingActionButton: FloatingActionButton(
      onPressed: () => controller.updateName("New"),
    ),
  );
}
```

## Related Topics

getx-navigation | layer-based-clean-architecture | dependency-injection

Overview

This skill describes using GetX for Flutter to implement simple, powerful reactive state management with clear structure and best practices. It focuses on controllers, bindings, reactive variables (.obs), and lifecycle hooks to keep UI code pure and maintainable. The guidance prioritizes dependency injection via Bindings and avoiding anti-patterns that couple UI and logic.

How this skill works

Controllers extend GetxController to hold state and business logic; observable fields use .obs and UI listens with Obx. Bindings decouple dependency injection from widgets and use Get.lazyPut for lazy initialization. Use onInit/onReady/onClose for lifecycle handling and prefer GetBuilder + update() for simple state, Obx for reactive updates.

When to use it

  • Small-to-medium Flutter apps that need lightweight, reactive state handling
  • Modular MVVM projects generated with get_cli or similar structure
  • When you want clear separation: controllers for logic, views for UI
  • Apps that benefit from lazy dependency injection and automatic disposal
  • When you need simple global or feature-scoped state without heavy boilerplate

Best practices

  • Organize modules with controllers/, bindings/, and views/ folders per feature
  • Use .obs for reactive variables and Obx in UI; use GetBuilder/update() for non-reactive, controller-driven updates
  • Register dependencies in Bindings with Get.lazyPut; avoid Get.put inline inside widgets
  • Never pass BuildContext into controllers; keep controllers context-free
  • Use onInit/onReady/onClose for setup and cleanup instead of initState/dispose
  • Avoid permanent: true unless a dependency must truly live for app lifetime

Example use cases

  • Simple counter or form state with a UserController and Obx-wrapped Text widgets
  • Authentication state management and route guarding via bindings and GetX navigation
  • Feature modules where each route has a Binding to lazy-load controllers and services
  • Lists and pagination where controllers fetch data and provide reactive list observables
  • Small utilities like theme or settings management without heavy state libraries

FAQ

When should I use Obx vs GetBuilder?

Use Obx for fine-grained, reactive updates with .obs variables. Use GetBuilder and controller.update() for simpler, less granular state updates where you control when rebuilds occur.

Where should I register controllers and services?

Register them in a Binding class for each module using Get.lazyPut. Bindings keep DI out of widgets and support lazy initialization and automatic disposal.