flutter
/

Flutter GetX – The Complete Guide to High‑Performance State Management

Last Sync: Today

On this page

12
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Flutter GetX – The Complete Guide to High‑Performance State Management

What is GetX?

GetX is an all‑in‑one Flutter package that provides high‑performance state management, intelligent dependency injection, and route management in a single solution. It is known for its simplicity, minimal boilerplate, and excellent performance. GetX combines reactive state management (using .obs variables), simple state management (via GetBuilder), dependency injection, navigation, and other utilities like internationalization, themes, and snackbars.

Why GetX?

    • Minimal boilerplate: GetX reduces the amount of code needed to manage state and navigation.
    • High performance: GetX only updates widgets that depend on changed values (reactive) or uses Obx for fine‑grained reactivity.
    • All‑in‑one: State management, navigation, dependency injection, and more in one package.
    • Simple syntax: No complex BuildContext manipulation for navigation or state.
    • Good for both small and large apps: Scales well.

Adding GetX to Your Project

Add the get package to your pubspec.yaml:

dependencies:
  get: ^4.6.5

Then run flutter pub get.

Replace MaterialApp with GetMaterialApp in your main.dart to enable GetX features.

DARTRead-only
1
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'GetX Demo',
      home: HomePage(),
    );
  }
}

Reactive State Management with .obs and Obx

The most common way to manage reactive state in GetX is to make variables .obs (observable) and wrap UI that uses them in Obx or GetX. When the observable changes, only the widgets inside Obx rebuild.

DARTRead-only
1
class CounterController extends GetxController {
  var count = 0.obs;

  void increment() => count++;
  void decrement() => count--;
}

In your UI:

DARTRead-only
1
class HomePage extends StatelessWidget {
  final CounterController c = Get.put(CounterController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX Counter')),
      body: Center(
        child: Obx(() => Text('Count: ${c.count}', style: TextStyle(fontSize: 24))),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: c.increment,
            child: Icon(Icons.add),
          ),
          SizedBox(width: 10),
          FloatingActionButton(
            onPressed: c.decrement,
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

Simple State Management with GetBuilder

For better performance in large apps, you can use GetBuilder which only updates when you manually call update() on the controller. This avoids the overhead of observing every variable.

DARTRead-only
1
class CounterController extends GetxController {
  int count = 0;

  void increment() {
    count++;
    update(); // triggers rebuild of GetBuilder widgets
  }
}

// In UI
GetBuilder<CounterController>(
  builder: (controller) => Text('Count: ${controller.count}'),
)

Dependency Injection

GetX provides several ways to inject dependencies: Get.put, Get.lazyPut, Get.find, and Get.create. These manage the lifecycle of controllers and services automatically.

DARTRead-only
1
// Put instance
Get.put(CounterController());

// Lazy initialization (created when first needed)
Get.lazyPut(() => CounterController());

// Find instance anywhere
final controller = Get.find<CounterController>();

// Create a new instance each time
Get.create(() => CounterController());

Navigation

GetX simplifies navigation with named routes, and you can navigate without context.

DARTRead-only
1
// Navigate to new screen
Get.to(SecondPage());

// Navigate with named route (define in GetMaterialApp routes)
Get.toNamed('/second');

// Pop
Get.back();

// Replace current screen
Get.off(ThirdPage());

// Remove all previous screens
Get.offAll(LoginPage());

// Pass arguments
Get.to(DetailPage(), arguments: {'id': 42});

// Receive arguments
var args = Get.arguments;

Snackbars, Dialogs, and BottomSheets

GetX provides easy‑to‑use methods for showing snackbars, dialogs, and bottom sheets without needing BuildContext.

DARTRead-only
1
// Snackbar
Get.snackbar('Title', 'Message', snackPosition: SnackPosition.BOTTOM);

// Dialog
Get.defaultDialog(title: 'Alert', middleText: 'This is a dialog');

// BottomSheet
Get.bottomSheet(Container(color: Colors.white, height: 200));

Internationalization and Themes

GetX also includes built‑in support for translations and themes, making it easy to create multilingual and theme‑switchable apps.

DARTRead-only
1
GetMaterialApp(
  translations: MyTranslations(),
  locale: Locale('en', 'US'),
  fallbackLocale: Locale('en', 'US'),
  theme: lightTheme,
  darkTheme: darkTheme,
  themeMode: ThemeMode.system,
  home: HomePage(),
)

// Change theme
Get.changeTheme(lightTheme);

// Change language
Get.updateLocale(Locale('fr', 'FR'));

Best Practices

    • Use GetX or Obx for reactive state when you need fine‑grained updates.
    • Use GetBuilder for simple state with manual update() to avoid overhead.
    • Use Get.lazyPut for controllers that may not be needed immediately to improve startup time.
    • Always dispose of resources if needed using onClose in the controller.
    • Keep controllers small and focused – one controller per feature/screen is a good practice.
    • Use named routes for better organisation.

Common Mistakes

    • Not using GetMaterialApp: Some GetX features (like Get.to) may still work, but others (like navigation with routes) won't.
    • Using Obx with non‑observable variables: Obx only tracks .obs variables; if you change a plain variable, the UI won't update.
    • Calling update() unnecessarily in GetBuilder – only call when state actually changes.
    • Not disposing of controllers: GetX disposes controllers automatically when the route is removed, but if you use Get.create, you need to manage disposal.
    • Over‑using Get.put in many places: Use dependency injection to centralise instance creation.

Key Takeaways

    • GetX is a powerful all‑in‑one solution for state management, navigation, and dependency injection.
    • Use .obs and Obx for reactive, auto‑updating state.
    • Use GetBuilder for manual updates to optimise performance.
    • Navigation is context‑free and simple.
    • GetX provides many utilities like snackbars, dialogs, and internationalisation.
    • Always use GetMaterialApp to enable all features.

Try it yourself

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'GetX Demo',
      home: HomePage(),
    );
  }
}

class CounterController extends GetxController {
  var count = 0.obs;
  void increment() => count++;
  void decrement() => count--;
}

class HomePage extends StatelessWidget {
  final CounterController c = Get.put(CounterController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX Counter')),
      body: Center(
        child: Obx(() => Text('Count: ${c.count}', style: TextStyle(fontSize: 24))),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: c.decrement,
            child: Icon(Icons.remove),
          ),
          SizedBox(width: 10),
          FloatingActionButton(
            onPressed: c.increment,
            child: Icon(Icons.add),
          ),
        ],
      ),
    );
  }
}

Test Your Knowledge

Q1
of 4

Which widget should you use to enable GetX features in your app?

A
MaterialApp
B
CupertinoApp
C
GetMaterialApp
D
GetApp
Q2
of 4

How do you make a variable reactive in GetX?

A
Use `var count = 0;`
B
Use `RxInt count = 0;`
C
Use `var count = 0.obs;`
D
Use `GetVariable(0)`
Q3
of 4

Which widget rebuilds when an observable changes?

A
GetBuilder
B
Obx
C
GetX
D
All of the above
Q4
of 4

How do you navigate to a new screen without a BuildContext?

A
Get.to(Page())
B
Navigator.push(context, Page())
C
RouteManager.go(Page())
D
GetX.navigate(Page())

Frequently Asked Questions

What is the difference between GetX and Provider?

GetX is a more complete solution that includes state management, navigation, and dependency injection. Provider focuses solely on state management and requires additional packages for navigation. GetX offers a reactive approach with .obs and Obx that is often more concise, and it doesn't require BuildContext for navigation. However, Provider is more aligned with Flutter's core concepts and may be preferred in some teams.

Should I use `Obx` or `GetBuilder`?

Obx is simpler and automatically rebuilds when any .obs variable used inside changes. GetBuilder gives you more control: it rebuilds only when you explicitly call update(). For performance, GetBuilder can be more efficient in large apps because you can control rebuilds. For small to medium apps, Obx is often sufficient.

How do I pass data between screens in GetX?

You can pass arguments using Get.to(DetailPage(), arguments: data). In the receiving screen, access Get.arguments. For more structured data, you can also use a controller and share it between pages (using Get.put and Get.find).

Does GetX work with Flutter Web?

Yes, GetX works on all platforms supported by Flutter, including web. However, some navigation features may behave slightly differently, but it's fully functional.

How do I test GetX controllers?

You can create a controller instance manually and test its methods. For widget tests, you can wrap your widget with GetMaterialApp and use Get.put or Get.lazyPut to inject the controller. The get_test package provides additional helpers.

Previous

flutter riverpod

Next

flutter texteditingcontroller

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.