Question #13MediumState Management

Getx fully including on generate , on init

#getx

Answer

Overview

GetX is an all-in-one Flutter package that provides state management, dependency injection, and route management in a lightweight, reactive way.


GetX Setup

yaml
dependencies:
  get: ^4.6.6
dart
void main() {
  runApp(GetMaterialApp(
    title: 'GetX App',
    initialRoute: '/',
    getPages: AppPages.routes, // onGenerateRoute equivalent
    home: HomeScreen(),
  ));
}

onGenerateRoute Equivalent in GetX

GetX uses

text
GetMaterialApp
with
text
getPages
instead of
text
onGenerateRoute
:

dart
// routes/app_pages.dart
class AppPages {
  static final routes = [
    GetPage(name: '/', page: () => HomeScreen()),
    GetPage(name: '/login', page: () => LoginScreen()),
    GetPage(
      name: '/profile',
      page: () => ProfileScreen(),
      binding: ProfileBinding(), // DI for this route
      middlewares: [AuthMiddleware()], // Route guards
    ),
    GetPage(
      name: '/product/:id', // Dynamic route parameter
      page: () => ProductDetailScreen(),
    ),
  ];
}

// Navigate by name
Get.toNamed('/profile');
Get.toNamed('/product/123');
Get.offAllNamed('/login'); // Clear stack and go to login

GetxController with onInit / onClose

dart
class HomeController extends GetxController {
  // Reactive state
  final count = 0.obs;
  final isLoading = false.obs;
  final items = <String>[].obs;

  
  void onInit() {
    super.onInit();
    // Called when controller is first created
    fetchData();
    ever(count, (_) => print('Count changed: $count'));
  }

  
  void onReady() {
    super.onReady();
    // Called after the widget is rendered on screen
    // Good for dialogs, navigation after build
  }

  
  void onClose() {
    // Called when controller is removed from memory
    // Clean up: close streams, cancel subscriptions
    super.onClose();
  }

  Future<void> fetchData() async {
    isLoading.value = true;
    await Future.delayed(Duration(seconds: 2));
    items.addAll(['Item 1', 'Item 2', 'Item 3']);
    isLoading.value = false;
  }

  void increment() => count.value++;
}

Using the Controller in Widget

dart
class HomeScreen extends StatelessWidget {
  final controller = Get.put(HomeController()); // Register + get

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX Demo')),
      body: Obx(() => // Rebuilds when observable changes
        controller.isLoading.value
          ? CircularProgressIndicator()
          : ListView.builder(
              itemCount: controller.items.length,
              itemBuilder: (_, i) => ListTile(title: Text(controller.items[i])),
            ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: Obx(() => Text('${controller.count}')),
      ),
    );
  }
}

GetX Workers (Reactive Listeners in onInit)

dart

void onInit() {
  super.onInit();

  // ever — runs every time value changes
  ever(count, (val) => print('Changed to $val'));

  // once — runs only on first change
  once(count, (_) => print('First change!'));

  // debounce — runs after 500ms of no changes
  debounce(searchQuery, (_) => search(), time: Duration(milliseconds: 500));

  // interval — runs at most every 1 second
  interval(counter, (_) => save(), time: Duration(seconds: 1));
}

Three GetX State Management Approaches

dart
// 1. Reactive (Obx + .obs) — auto-rebuilds
final name = 'Alice'.obs;
Obx(() => Text(name.value));

// 2. Simple (GetBuilder + update()) — manual refresh
class MyController extends GetxController {
  int count = 0;
  void increment() { count++; update(); } // Call update() to rebuild
}
GetBuilder<MyController>(builder: (c) => Text('${c.count}'));

// 3. MixinBuilder — hybrid of both
GetX<MyController>(builder: (c) => Text('${c.count.value}'));

Summary: GetX provides

text
onInit
(setup),
text
onReady
(post-build), and
text
onClose
(teardown). Use
text
GetMaterialApp
with
text
getPages
for named routing, and
text
.obs
+
text
Obx
for reactive state.

Additional Resources