Flutter GetX
All-in-one solution for state, routing, and dependency injection
⚡ What is GetX?
GetX is a lightweight, powerful Flutter solution combining state management, routing, and dependency injection. It offers minimal boilerplate, high performance, and reactive programming with simple syntax, making development faster and more enjoyable for all skill levels.
// Simple reactive variable
final count = 0.obs;
Key Concepts
Simple State
Minimal boilerplate code
final name = 'John'.obs;
name.value = 'Jane';
Fast Routing
Navigate without context
Get.to(NextPage());
Get.back();
Dependency Injection
Easy dependency management
Get.put(Controller());
Get.find<Controller>()
High Performance
Optimized rebuilds
Obx(() =>
Text('${count}'))
🔹 Installation
Add GetX to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
get: ^4.6.5
Then run:
flutter pub get
🔹 Basic Counter Example
Create a counter using GetX:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// 1. Create a Controller
class CounterController extends GetxController {
// Observable variable
var count = 0.obs;
void increment() {
count++;
}
void decrement() {
count--;
}
}
// 2. Use GetMaterialApp instead of MaterialApp
void main() {
runApp(GetMaterialApp(
home: CounterPage(),
));
}
// 3. Use the controller in your widget
class CounterPage extends StatelessWidget {
// Instantiate controller
final CounterController controller = Get.put(CounterController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('GetX Counter')),
body: Center(
// Obx rebuilds only this widget
child: Obx(() => Text(
'${controller.count}',
style: TextStyle(fontSize: 48),
)),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}
Output:
A counter app that increments when the button is pressed using GetX.
🔹 Reactive State Management
Three ways to make variables reactive:
class MyController extends GetxController {
// Method 1: .obs (Observable)
var name = 'John'.obs;
var age = 25.obs;
var isActive = true.obs;
// Method 2: Rx types
RxString email = '[email protected]'.obs;
RxInt score = 0.obs;
RxList<String> items = <String>[].obs;
// Method 3: GetBuilder (simple state)
int counter = 0;
void updateName(String newName) {
name.value = newName; // Update observable
}
void incrementCounter() {
counter++;
update(); // Manually trigger rebuild for GetBuilder
}
}
// Usage in UI
class MyWidget extends StatelessWidget {
final controller = Get.put(MyController());
@override
Widget build(BuildContext context) {
return Column(
children: [
// Obx for reactive variables
Obx(() => Text(controller.name.value)),
// GetBuilder for simple state
GetBuilder<MyController>(
builder: (ctrl) => Text('${ctrl.counter}'),
),
],
);
}
}
Output:
Different approaches to reactive state management in GetX.
🔹 Navigation with GetX
Navigate without BuildContext:
// Simple navigation
Get.to(NextPage());
// Named routes
Get.toNamed('/details');
// Go back
Get.back();
// Replace current page
Get.off(HomePage());
// Clear all and go to page
Get.offAll(LoginPage());
// Pass data
Get.to(DetailsPage(), arguments: {'id': 123});
// Receive data
final args = Get.arguments;
// Show snackbar
Get.snackbar(
'Title',
'Message',
snackPosition: SnackPosition.BOTTOM,
);
// Show dialog
Get.defaultDialog(
title: 'Alert',
middleText: 'Are you sure?',
onConfirm: () => Get.back(),
);
// Show bottom sheet
Get.bottomSheet(
Container(
height: 200,
color: Colors.white,
child: Center(child: Text('Bottom Sheet')),
),
);
Output:
Various navigation methods available in GetX without needing context.
🔹 Dependency Injection
Manage dependencies easily:
// Put: Create and keep in memory
Get.put(ApiController());
// Lazy: Create only when needed
Get.lazyPut(() => DatabaseController());
// Put async: For async initialization
Get.putAsync(() async {
final controller = await ApiController.init();
return controller;
});
// Find: Get existing instance
final api = Get.find<ApiController>();
// Delete: Remove from memory
Get.delete<ApiController>();
// Example usage
class ApiController extends GetxController {
Future<void> fetchData() async {
// API logic
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get the controller
final api = Get.find<ApiController>();
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => api.fetchData(),
child: Text('Fetch Data'),
),
),
);
}
}
Output:
Dependency injection patterns in GetX for managing controllers and services.
🔹 Todo List Example
A complete example with GetX:
class TodoController extends GetxController {
var todos = <String>[].obs;
var textController = TextEditingController();
void addTodo() {
if (textController.text.isNotEmpty) {
todos.add(textController.text);
textController.clear();
Get.snackbar('Success', 'Todo added!');
}
}
void removeTodo(int index) {
todos.removeAt(index);
}
@override
void onClose() {
textController.dispose();
super.onClose();
}
}
class TodoPage extends StatelessWidget {
final controller = Get.put(TodoController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('GetX Todo List')),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller.textController,
decoration: InputDecoration(
hintText: 'Enter todo',
),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: controller.addTodo,
),
],
),
),
Expanded(
child: Obx(() => ListView.builder(
itemCount: controller.todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(controller.todos[index]),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => controller.removeTodo(index),
),
);
},
)),
),
],
),
);
}
}
Output:
A complete todo list app with add and remove functionality using GetX.
🔹 GetX Utilities
Helpful utilities built into GetX:
// Responsive design
Get.width; // Screen width
Get.height; // Screen height
Get.context; // BuildContext
Get.theme; // ThemeData
// Platform checks
GetPlatform.isAndroid;
GetPlatform.isIOS;
GetPlatform.isWeb;
// Internationalization
Get.locale; // Current locale
Get.updateLocale(Locale('es', 'ES'));
// Theme switching
Get.changeTheme(ThemeData.dark());
Get.changeThemeMode(ThemeMode.dark);
// Validation
GetUtils.isEmail('[email protected]');
GetUtils.isPhoneNumber('+1234567890');
GetUtils.isURL('https://example.com');
Output:
Various utility functions provided by GetX for common tasks.
🔹 When to Use GetX
✅ Good For:
- Rapid development and prototyping
- Small to medium-sized apps
- When you want an all-in-one solution
- Developers who prefer minimal boilerplate
- Apps needing simple navigation and state
❌ Consider Alternatives For:
- Very large enterprise applications
- Teams preferring official Google solutions
- When you need strict architectural patterns
- Projects requiring extensive testing frameworks
🔹 GetX Best Practices
- Use Get.lazyPut(): For better memory management
- Dispose controllers: Override onClose() to clean up resources
- Use Obx sparingly: Only wrap widgets that need to rebuild
- Separate business logic: Keep controllers focused and testable
- Use GetView: For widgets that use a single controller