get_ex 1.0.1 copy "get_ex: ^1.0.1" to clipboard
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.

get_ex #

pub package License: MIT Flutter

A complete, self-contained state management, dependency injection, and navigation solution for Flutter — inspired by the GetX pattern with zero external dependencies.


Features #

Category Highlights
Reactive State Rx<T>, RxInt, RxDouble, RxString, RxBool, RxList, RxMap, RxSet with .obs
Controllers GetXController with onInit / onReady / onClose lifecycle
StateMixin RxStatus-based async state (loading, success, error, empty)
Dependency Injection put · lazyPut · putAsync · create · find · delete
Bindings GetXBindings / GetXBindingsBuilder for route-scoped DI
Reactive Builders GetXBuilder auto-tracking widget, obx() helper
Workers ever · once · interval · debounce
Navigation to · off · offAll · toNamed · offNamed · offAllNamed with middleware
Transitions 11 built-in types (fade, slide, zoom, size, cupertino, material, …)
Snackbar / Dialog / Overlay Overlay-based snackbar, dialogs, bottom sheets, loading indicator
i18n GetXTranslations with .tr / .trParams() extensions
Theming Reactive GetXTheme with dark mode detection
Platform GetXPlatform detection for Android, iOS, Web, macOS, Windows, Linux
Logger Configurable GetXLog with custom writers
Extensions String, num, Duration, BuildContext, Widget utilities

Getting Started #

Installation #

Add get_ex to your pubspec.yaml:

dependencies:
  get_ex: ^1.0.0

Then run:

flutter pub get

Import #

import 'package:get_ex/get_ex.dart';

Quick Start #

Replace MaterialApp with GetXApp and you're ready:

void main() => runApp(
  GetXApp(
    title: 'My App',
    home: HomePage(),
    initialBinding: HomeBinding(),
  ),
);

Usage #

Reactive State Management #

Create reactive variables with .obs and rebuild the UI automatically with GetXBuilder:

// Declare reactive state
final count = 0.obs;
final name = 'Flutter'.obs;
final items = <String>[].obs;

// Update state — UI rebuilds automatically
count.value++;
name.value = 'Dart';
items.add('New item');
// In your widget tree
GetXBuilder(
  builder: () => Text('Count: ${count.value}'),
)

Controllers #

Extend GetXController for organized state with lifecycle hooks:

class CounterController extends GetXController {
  final count = 0.obs;

  @override
  void onInit() {
    super.onInit();
    ever(count, (val) => GetXLog.info('Count changed to $val'));
  }

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

  @override
  void onClose() {
    super.onClose();
    // Clean up resources
  }
}

StateMixin for Async Operations #

class UserController extends GetXController with StateMixin<User> {
  @override
  void onInit() {
    super.onInit();
    fetchUser();
  }

  Future<void> fetchUser() async {
    change(null, status: RxStatus.loading());
    try {
      final user = await api.getUser();
      change(user, status: RxStatus.success());
    } catch (e) {
      change(null, status: RxStatus.error(e.toString()));
    }
  }
}
// In the UI
controller.obx(
  (user) => Text(user.name),
  onLoading: CircularProgressIndicator(),
  onError: (error) => Text('Error: $error'),
  onEmpty: Text('No data'),
)

Dependency Injection #

// Register
GetX.put(CounterController());
GetX.lazyPut(() => ApiService());
await GetX.putAsync(() async => await Database.init());
GetX.create(() => Logger()); // new instance every find()

// Resolve
final controller = GetX.find<CounterController>();

// Remove
GetX.delete<CounterController>();

Bindings #

Group dependencies per route:

class HomeBinding extends GetXBindings {
  @override
  void dependencies() {
    GetX.lazyPut(() => HomeController());
    GetX.lazyPut(() => HomeRepository());
  }
}

Or inline:

GetXBindingsBuilder(() {
  GetX.lazyPut(() => HomeController());
});
// Push
GetX.to(SecondPage());

// Push and remove current
GetX.off(SecondPage());

// Push and remove all
GetX.offAll(LoginPage());

// Go back
GetX.back();

// Named routes
GetX.toNamed('/details');
GetX.offNamed('/home');
GetX.offAllNamed('/login');

Define named routes in GetXApp:

GetXApp(
  initialRoute: '/',
  getPages: [
    GetXPage(name: '/', page: () => HomePage(), binding: HomeBinding()),
    GetXPage(name: '/details', page: () => DetailsPage()),
    GetXPage(
      name: '/profile',
      page: () => ProfilePage(),
      middlewares: [AuthMiddleware()],
      transition: GetXTransition.fade,
    ),
  ],
)

Middleware #

class AuthMiddleware extends GetXMiddleware {
  @override
  int get priority => 1;

  @override
  RouteSettings? redirect(String? route) {
    final isLoggedIn = GetX.find<AuthService>().isLoggedIn;
    return isLoggedIn ? null : const RouteSettings(name: '/login');
  }
}

Transitions #

Apply transitions per-route or per-navigation call:

GetX.to(
  NextPage(),
  transition: GetXTransition.rightToLeft,
  duration: Duration(milliseconds: 300),
  curve: Curves.easeInOut,
);

Available transitions: fade, rightToLeft, leftToRight, upToDown, downToUp, zoom, size, cupertino, material, native, noTransition.

Workers #

React to reactive variable changes:

// Called every time value changes
ever(count, (val) => print('count is $val'));

// Called only on first change
once(count, (val) => print('first change: $val'));

// Called at most once per second
interval(count, (val) => print('interval: $val'), time: 1.seconds);

// Called after 800ms of no changes
debounce(count, (val) => print('debounce: $val'), time: 800.milliseconds);

Snackbar #

GetXSnackbarHelper.show(
  context: context,
  snackbar: GetXSnackbar(
    title: 'Success',
    message: 'Item saved!',
    duration: Duration(seconds: 3),
    snackPosition: GetXSnackPosition.top,
  ),
);

Dialog #

// Default dialog
GetXDialog.defaultDialog(
  context: context,
  title: 'Confirm',
  middleText: 'Delete this item?',
  onConfirm: () => deleteItem(),
);

// Bottom sheet
GetXDialog.bottomSheet(
  context: context,
  builder: (_) => MyBottomSheetContent(),
);

Loading Overlay #

GetXOverlay.show(context: context);
// ... perform work
GetXOverlay.dismiss();

Internationalization #

Define translations:

class AppTranslations extends GetXTranslations {
  @override
  Map<String, Map<String, String>> get keys => {
    'en_US': {
      'greeting': 'Hello @name!',
      'title': 'My App',
    },
    'es_ES': {
      'greeting': '¡Hola @name!',
      'title': 'Mi App',
    },
  };
}

Use in widgets:

Text('greeting'.trParams({'name': 'Flutter'}))
Text('title'.tr)

Switch locale at runtime:

GetXTranslationService.updateLocale(const Locale('es', 'ES'));

Theming #

// Change theme
GetXTheme.changeTheme(ThemeData.dark());

// Toggle theme mode
GetXTheme.changeThemeMode(ThemeMode.dark);

// Check dark mode
if (GetXTheme.isDarkMode) { ... }

Platform Detection #

if (GetXPlatform.isWeb) { ... }
if (GetXPlatform.isAndroid) { ... }
if (GetXPlatform.isDesktop) { ... }
if (GetXPlatform.isMobile) { ... }

Extensions #

// String
'hello world'.capitalize;        // 'Hello world'
'hello world'.capitalizeFirst;   // 'Hello World'
'test@email.com'.isEmail;        // true

// Num → Duration
2.seconds;
500.milliseconds;
await 1.5.seconds.delay(() => print('Done'));

// Context
context.width;
context.height;
context.isPhone;
context.isTablet;

// Widget
myWidget.paddingAll(16);
myWidget.marginSymmetric(horizontal: 8);
myWidget.onTap(() => doSomething());

Logging #

GetXLog.info('User loaded');
GetXLog.warning('Cache miss');
GetXLog.error('Failed to connect');

// Configure
GetXLog.config(
  enableLog: true,
  minLevel: GetXLogLevel.warning,
  logWriterCallback: (message, level) => myLogger.log(message),
);

Full Example #

See the example directory for a complete app demonstrating:

  • Counter with reactive Rx state
  • Todo list with GetXController + RxList
  • Named routing with middleware
  • Dependency injection via bindings
  • Snackbar and dialog
  • Internationalization with locale switching
  • Theme switching

Run it:

cd example
flutter pub get
flutter run

Architecture #

lib/
├── get_ex.dart                         # Barrel export
└── src/
    ├── get_x_main.dart                 # GetXApp + GetX facade
    ├── di/
    │   ├── get_x_instance.dart         # DI container
    │   └── get_x_binding.dart          # Bindings
    ├── state/
    │   ├── get_x_controller.dart       # Controller base
    │   ├── get_x_state.dart            # StateMixin / RxStatus
    │   └── rx_types/
    │       ├── rx_core.dart            # Rx<T> and typed variants
    │       └── rx_notifier.dart        # ValueNotifier wrapper
    ├── rx/
    │   ├── get_x_obs.dart              # GetXBuilder / obx
    │   └── get_x_workers.dart          # ever / once / interval / debounce
    ├── navigation/
    │   ├── get_x_navigation.dart       # Navigation API
    │   ├── get_x_route.dart            # GetXPage model
    │   ├── get_x_router_delegate.dart  # Router delegate
    │   ├── get_x_middleware.dart        # Middleware
    │   └── transitions/
    │       └── get_x_transition.dart   # Transition animations
    ├── ui/
    │   ├── snackbar/get_x_snackbar.dart
    │   ├── dialog/get_x_dialog.dart
    │   └── overlay/get_x_overlay.dart
    ├── i18n/
    │   ├── get_x_translations.dart     # Translation service
    │   └── get_x_locale.dart           # Locale utilities
    ├── theme/
    │   └── get_x_theme.dart            # Reactive theming
    └── utils/
        ├── get_x_extensions.dart       # Convenience extensions
        ├── get_x_platform.dart         # Platform detection
        └── get_x_logger.dart           # Logger

Requirements #

  • Dart SDK: >=3.0.0 <4.0.0
  • Flutter: >=3.10.0
  • Dependencies: None (only Flutter SDK)

Contributing #

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please ensure your code passes flutter analyze with no issues before submitting.


License #

This project is licensed under the MIT License — see the LICENSE file for details.

0
likes
155
points
22
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

State management, DI, and navigation for Flutter. Reactive Rx types, controllers, routing, transitions, snackbars, dialogs, i18n, and theming with zero external dependencies.

Repository (GitHub)
View/report issues

Topics

#state-management #dependency-injection #navigation #reactive #getx

License

MIT (license)

Dependencies

flutter

More

Packages that depend on get_ex