get_ex 1.0.1
get_ex: ^1.0.1 copied to clipboard
State management, DI, and navigation for Flutter. Reactive Rx types, controllers, routing, transitions, snackbars, dialogs, i18n, and theming with zero external dependencies.
example/lib/main.dart
// Complete example app demonstrating get_x features:
// - Counter with Rx reactive state
// - Todo list with GetXController + RxList
// - Named routing with middleware
// - DI bindings
// - Snackbar and dialog
// - Internationalization
import 'package:flutter/material.dart';
import 'package:get_ex/get_ex.dart';
// ---------------------------------------------------------------------------
// Translations
// ---------------------------------------------------------------------------
class AppTranslations extends GetXTranslations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
'title': 'GetX Example',
'counter': 'Counter',
'todos': 'Todos',
'increment': 'Increment',
'add_todo': 'Add Todo',
'greeting': 'Hello @name!',
'switch_lang': 'Switch to Spanish',
},
'es_ES': {
'title': 'Ejemplo GetX',
'counter': 'Contador',
'todos': 'Tareas',
'increment': 'Incrementar',
'add_todo': 'Agregar Tarea',
'greeting': '¡Hola @name!',
'switch_lang': 'Cambiar a Inglés',
},
};
}
// ---------------------------------------------------------------------------
// Controllers
// ---------------------------------------------------------------------------
class CounterController extends GetXController {
final count = 0.obs;
late GetXWorker _logWorker;
@override
void onInit() {
super.onInit();
_logWorker = ever(count, (val) {
GetXLog.info('Counter changed to $val');
});
}
void increment() => count.value++;
void decrement() => count.value--;
@override
void onClose() {
_logWorker.dispose();
super.onClose();
}
}
class TodoController extends GetXController {
final todos = <String>[].obs;
final textController = TextEditingController();
void addTodo() {
final text = textController.text.trim();
if (text.isNotEmpty) {
todos.add(text);
textController.clear();
}
}
void removeTodo(int index) => todos.removeAt(index);
@override
void onClose() {
textController.dispose();
super.onClose();
}
}
// ---------------------------------------------------------------------------
// Bindings
// ---------------------------------------------------------------------------
class HomeBinding extends GetXBindings {
@override
void dependencies() {
GetX.lazyPut(() => CounterController());
}
}
class TodoBinding extends GetXBindings {
@override
void dependencies() {
GetX.lazyPut(() => TodoController());
}
}
// ---------------------------------------------------------------------------
// Middleware
// ---------------------------------------------------------------------------
class LogMiddleware extends GetXMiddleware {
@override
int get priority => 0;
@override
GetXPage? onPageCalled(GetXPage? page) {
GetXLog.info('Navigating to: ${page?.name}');
return page;
}
}
// ---------------------------------------------------------------------------
// Pages
// ---------------------------------------------------------------------------
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('title'.tr),
actions: [
IconButton(
icon: const Icon(Icons.language),
onPressed: () {
final isEnglish =
GetXLocale.currentLocale.languageCode == 'en';
GetX.updateLocale(
isEnglish
? const Locale('es', 'ES')
: const Locale('en', 'US'),
);
},
),
IconButton(
icon: const Icon(Icons.brightness_6),
onPressed: () {
GetX.changeThemeMode(
GetX.isDarkMode ? ThemeMode.light : ThemeMode.dark,
);
},
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'greeting'.trParams({'name': 'Developer'}),
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: () => GetX.toNamed('/counter'),
child: Text('counter'.tr),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => GetX.toNamed('/todos'),
child: Text('todos'.tr),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
GetX.snackbar(
context,
'Hello!',
'This is a GetX snackbar',
snackPosition: GetXSnackPosition.top,
backgroundColor: Colors.blueAccent,
);
},
child: const Text('Show Snackbar'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
GetX.defaultDialog(
context,
title: 'GetX Dialog',
content: const Text('This is a default dialog.'),
textConfirm: 'OK',
textCancel: 'Cancel',
onConfirm: () => GetXLog.info('Confirmed!'),
);
},
child: const Text('Show Dialog'),
),
],
),
),
);
}
}
class CounterPage extends StatelessWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context) {
final controller = GetX.find<CounterController>();
return Scaffold(
appBar: AppBar(title: Text('counter'.tr)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
obx(() => Text(
'${controller.count.value}',
style: Theme.of(context).textTheme.displayLarge,
)),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
heroTag: 'decrement',
onPressed: controller.decrement,
child: const Icon(Icons.remove),
),
const SizedBox(width: 16),
FloatingActionButton(
heroTag: 'increment',
onPressed: controller.increment,
child: const Icon(Icons.add),
),
],
),
],
),
),
);
}
}
class TodoPage extends StatelessWidget {
const TodoPage({super.key});
@override
Widget build(BuildContext context) {
final controller = GetX.find<TodoController>();
return Scaffold(
appBar: AppBar(title: Text('todos'.tr)),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller.textController,
decoration: InputDecoration(
hintText: 'add_todo'.tr,
border: const OutlineInputBorder(),
),
onSubmitted: (_) => controller.addTodo(),
),
),
const SizedBox(width: 8),
IconButton(
icon: const 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: const Icon(Icons.delete),
onPressed: () => controller.removeTodo(index),
),
);
},
)),
),
],
),
);
}
}
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
void main() {
GetX.config(enableLog: true);
runApp(
GetXApp(
title: 'GetX Example',
initialRoute: '/',
translations: AppTranslations(),
locale: const Locale('en', 'US'),
fallbackLocale: const Locale('en', 'US'),
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false,
pages: [
GetXPage(
name: '/',
page: () => const HomePage(),
middlewares: [LogMiddleware()],
),
GetXPage(
name: '/counter',
page: () => const CounterPage(),
binding: HomeBinding(),
transition: GetXTransition.fade,
middlewares: [LogMiddleware()],
),
GetXPage(
name: '/todos',
page: () => const TodoPage(),
binding: TodoBinding(),
transition: GetXTransition.rightToLeft,
middlewares: [LogMiddleware()],
),
],
),
);
}