A fully annotated Flutter project implementing every core concept of the
getpackage, built as an interactive educational hub with a fully working Real-World E-Commerce app demo.
π± Cross-Platform Ready: This project perfectly supports and is optimized for Android, iOS, and Chrome (Web). You can easily learn and explore the concepts by running it directly on any of these platforms!
β‘ Try it now on Android: For ease of setup, you can directly install and test the app on your Android device by downloading the APK here:
π₯ Download Android APK (v1.0.0)
This project teaches you 8 core GetX concepts and how to tie them together in a production-level application, entirely through working, commented code:
| # | Concept | File(s) |
|---|---|---|
| 1 | Reactive State (Rx & Obx) |
screens/concept_screens/reactive_state_screen.dart |
| 2 | Simple State (GetBuilder & update()) |
screens/concept_screens/simple_state_screen.dart |
| 3 | Dependency Injection (Get.put, lazyPut, find) |
screens/concept_screens/dependency_injection_screen.dart |
| 4 | Route Management (Named Routes, parameters) | screens/concept_screens/route_management_screen.dart |
| 5 | Bindings (Decoupling DI from UI) | bindings/concept_bindings.dart, screens/concept_screens/bindings_screen.dart |
| 6 | Controllers & Lifecycles (onInit, onClose) |
controllers/concept_controllers/, screens/concept_screens/controller_lifecycle_screen.dart |
| 7 | Route Guards (GetMiddleware) |
middlewares/, screens/concept_screens/middleware_screen.dart |
| 8 | Theming & Localization (.tr, ThemeMode) |
translations/app_translations.dart, screens/concept_screens/theme_i18n_screen.dart |
| 9 | Real-World E-Commerce Demo | screens/real_world_screens/, controllers/ |
lib/
βββ main.dart # App entry point β Named routes, Bindings & Theme setup
βββ models/ # Data classes (Product, User, etc.)
βββ controllers/
β βββ auth_controller.dart # Global authentication state
β βββ cart_controller.dart # Manages cart logic globally
β βββ store_controller.dart # Manages products, pagination, and search
β βββ profile_controller.dart # Demonstrates fenix: true and routing parameters
βββ screens/
β βββ home_screen.dart # π Hub screen β links to all demos
β βββ concept_screens/ # π Individual isolated demo screens for each concept
β βββ real_world_screens/ # ποΈ E-Commerce demo (Catalog, Detail, Cart, Profile)
βββ bindings/ # π Decoupled dependency injection files
βββ middlewares/ # π‘οΈ Route interceptors for auth protection
βββ translations/ # π Multi-language dictionaries
- Flutter SDK (3.x+)
- Dart 3.x
- Android Studio / VS Code with Flutter plugin
# Clone and navigate to the project
cd GetXStateManagement
# Install dependencies
flutter pub get
# Run the app (Works on iOS, Android, and Web)
flutter runAdd get to pubspec.yaml:
dependencies:
get: ^4.6.6 # Or latest versionChange MaterialApp to GetMaterialApp in main.dart:
import 'package:get/get.dart';
void main() => runApp(GetMaterialApp(home: Home()));GetX makes reactive programming incredibly simple without Streams or complex setup.
Creating the State:
class CounterController extends GetxController {
final count = 0.obs; // .obs makes it an Observable!
void increment() {
count.value++; // Access the value using .value
}
}Listening in UI:
Obx(() => Text('Count: ${controller.count.value}')) // Automatically rebuilds!Key insight: You don't need
StatefulWidgetorsetState. Just wrap the exact widget that needs to change inObx()!
GetX has its own built-in DI system, eliminating the need for Provider entirely.
Injecting a Controller:
// Instantiated immediately
Get.put(AuthController());
// Instantiated only when used
Get.lazyPut(() => CartController());Finding a Controller anywhere:
final auth = Get.find<AuthController>();Navigate without context anywhere in your app!
// Go to a named route
Get.toNamed('/cart');
// Go back
Get.back();
// Replace current screen (no back button)
Get.offNamed('/login');
// Clear entire stack
Get.offAllNamed('/home');
// Pass parameters
Get.toNamed('/profile?tab=orders');
print(Get.parameters['tab']); // "orders"Keep your UI clean by decoupling Dependency Injection.
Creating a Binding:
class StoreBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => StoreController());
}
}Applying it in routing:
GetPage(
name: '/store',
page: () => StoreScreen(),
binding: StoreBinding(), // Automatically injects and disposes!
)Controllers have their own lifecycles completely decoupled from the Widget tree.
class SearchController extends GetxController {
@override
void onInit() {
super.onInit();
// Called immediately when controller is created
}
@override
void onClose() {
// Called immediately before controller is deleted from memory
super.onClose();
}
}Protect routes easily using interceptors.
class AuthGuard extends GetMiddleware {
@override
RouteSettings? redirect(String? route) {
if (!Get.find<AuthController>().isLoggedIn.value) {
// Intercept and redirect unauthenticated users
return const RouteSettings(name: '/login');
}
return null;
}
}Change themes and languages instantly without restarting the app.
Translations:
Text('hello'.tr); // Appends .tr to translate instantly
Get.updateLocale(Locale('es', 'ES')); // Changes app language liveTheming:
Get.changeThemeMode(ThemeMode.dark); // Switches to dark mode instantlyThis app isn't just theory. It contains a fully working mini Tech Store to show GetX in action:
GetMaterialApp (Root setup, themes, routes)
β
βΌ
AuthController (Global singleton managing auth state)
β
βΌ
StoreController (Handles products, search, and pagination)
β
βΌ
ProductCatalogScreen (Uses Obx & Bindings)
β
βΌ
CartController (Global logic for cart modifications)
β
βΌ
MiddlewareGuard (Intercepts unauthenticated checkout attempts)
ββββββββββββββββ
β Screens β β UI only. Highly optimized with GetView & Obx.
ββββββββββββββββ€
β Controllers β β Business logic & State. Extends GetxController.
ββββββββββββββββ€
β Bindings β β Dependency Injection mapping.
ββββββββββββββββ€
β Models β β Pure data classes.
ββββββββββββββββ
- Say goodbye to Context: Routing, Snackbars, and Dialogs can all be triggered using
Get.back()orGet.snackbar()without needingBuildContext. - Obx is your best friend: Wrap only the smallest possible widget inside
Obx()for maximum performance. - Keep UI dumb: Put all your logic, API calls, and state management inside a
GetxController. - Use Bindings for clean architecture: Don't bloat your
main.dartwithGet.put. Let bindings handle memory management automatically.
dependencies:
flutter:
sdk: flutter
get: ^4.6.6- π¦ Package: get on pub.dev
- π Official Docs: GetX Documentation
Built as a comprehensive Flutter learning resource β every concept is clearly explained with live demos, code snippets, and real-world implementation.
This project is licensed under the MIT License - see the LICENSE file for details.
This repository is provided for portfolio and evaluation purposes only.
Commercial use, redistribution, modification, or reproduction without written permission is prohibited.
Developed with β€οΈ by Arpit Aswal.