GetX — лёгкий микро-фреймворк для Flutter, объединяющий управление состоянием, навигацию и внедрение зависимостей в одном пакете. Разработанный Амир Хоссейн Абдорашиди, GetX предлагает минимальный boilerplate: без Stream, без ChangeNotifier, без BuildContext для навигации. По данным pub.dev, GetX набрал более 13 тысяч лайков, став одним из самых популярных Flutter-пакетов.
Главное
GetX — all-in-one микро-фреймворк для Flutter, решающий три основные задачи разработки: управление состоянием (State Management), навигация (Routing) и внедрение зависимостей (DI). GetX не требует Stream, ChangeNotifier, Builders или подписок — всю реактивность обеспечивают Rx-обёртки на основе GetValue и GetStream, работающие в десятки раз быстрее ChangeNotifier.
GetX позиционируется как альтернатива связке Provider + Navigator + get_it/kiwi. Вместо установки трёх разных пакетов и написания 10 строк конфигурации, GetX даёт всё из коробки с одной строкой: GetMaterialApp вместо MaterialApp. Навигация работает через Get.to(NextScreen()) без BuildContext, а DI — через Get.put(Service()) без Provider-дерева.
По данным Flutter Community Survey 2025, GetX используется в 43% Flutter-проектов. Основные причины выбора: минимальный порог входа (5 минут на освоение), отсутствие boilerplate (код сокращается на 60-70% по сравнению с Provider или BLoC) и быстрая разработка MVP. Критики отмечают нарушение принципа разделения ответственности и сложность отладки.
Obx — реактивный виджет GetX, перестраивающийся при изменении Rx-переменных. Obx не требует подписки, dispose или Builder-функций — достаточно обернуть виджет в Obx и использовать внутри Rx-переменную. Obx автоматически отслеживает, какие Rx-переменные используются, и перерисовывает только при их изменении.
class CounterController extends GetxController {
final count = 0.obs;
void increment() => count++;
}
class CounterScreen extends StatelessWidget {
final controller = Get.put(CounterController());
@override
Widget build(context) => Obx(() => Text('${controller.count}'));
}Rx-переменные: .obs — геттер, оборачивающий любое значение в Rx-объект. GetX предоставляет типизированные Rx-классы: RxInt, RxString, RxDouble, RxBool, RxList, RxMap. Все Rx-переменные ведут себя как обычные примитивы: count++, name.value = 'Hello', items.add(item). Изменение автоматически уведомляет Obx-подписчиков.
GetBuilder — альтернатива Obx без Rx, работающая через ручной вызов update(). GetBuilder.filter — для точечного обновления по ID-ключам. Obx быстрее (автоматическое отслеживание зависимостей), GetBuilder предсказуемее (явный вызов обновления). Рекомендуется Obx для простых сценариев и GetBuilder для сложных виджетов с множеством зависимостей.
GetxController — базовый класс для бизнес-логики с поддержкой жизненного цикла. GetxController имеет методы: onInit() (инициализация), onReady() (после первого фрейма), onClose() (очистка ресурсов). В отличие от ChangeNotifier и StateNotifier, GetxController автоматически управляет подписками: при уничтожении страницы все Rx-переменные и Workers отписываются.
class AuthController extends GetxController {
final user = Rx<User?>(null);
final isLoading = false.obs;
@override
void onInit() {
ever(isLoading, (_) => print('Loading: $isLoading'));
super.onInit();
}
Future<void> login(String email, String password) async {
isLoading.value = true;
user.value = await api.login(email, password);
isLoading.value = false;
}
}Workers — реактивные утилиты GetX: ever (вызывается при каждом изменении), once (только при первом изменении), debounce (с задержкой), interval (не чаще N раз в секунду). Workers решают типовые задачи: валидация полей (debounce), аналитика (once), синхронизация (ever). Workers автоматически отписываются при вызове onClose(), предотвращая утечки.
GetX навигация не требует BuildContext для перехода между экранами. Вместо Navigator.push(context, MaterialPageRoute(...)) используется Get.to(NextScreen()) — вызов из любого места, включая Controller без доступа к BuildContext. GetX поддерживает именованные маршруты, анимации, middleware и передачу аргументов без MaterialPageRoute.
// Обычная навигация
Get.to(ProfileScreen());
Get.back();
Get.off(LoginScreen()); // заменить текущий маршрут
Get.offAll(HomeScreen()); // очистить стек
// Именованные маршруты
Get.toNamed('/profile', arguments: 'user123');
Get.offNamed('/login');
// Middleware
GetPage(
name: '/profile',
page: () => ProfileScreen(),
middlewares: [AuthMiddleware()],
)GetPage и GetPages: GetX использует GetPages вместо routes в MaterialApp. Middleware — проверка авторизации, редиректы, аналитика перед входом на экран. Transition — встроенные анимации перехода: fadeIn, zoom, leftToRight, topToBottom. Bindings — класс, инициализирующий Controller и зависимости при входе на маршрут. Bindings решают проблему ленивой инициализации: Controller создаётся только когда экран открыт.
Get.put — регистрация экземпляра в DI-контейнере. Get.find — получение экземпляра из контейнера. Get.lazyPut — ленивая инициализация (создаётся при первом вызове find). Get.putAsync — асинхронная инициализация (для сервисов с init). Get.delete — удаление из контейнера (вызывается автоматически Bindings при уничтожении маршрута).
| Метод | Когда создаётся | Когда удаляется |
|---|---|---|
| Get.put | Немедленно | Get.delete или onClose |
| Get.lazyPut | При первом find | Get.delete или onClose |
| Get.putAsync | После выполнения Future | Get.delete или onClose |
| Get.create | При каждом find (новая фабрика) | Нет |
GetX DI — простейший DI-контейнер во Flutter. Нет Provider-дерева, нет Module, нет Scope. Get.put(Repository()) в Controller или main.dart делает объект доступным в любом месте приложения через Get.find<Repository>(). GetX DI также поддерживает тегирование (tag: 'api') и перманентность (permanent: true) для предотвращения удаления.
Производительность GetX основана на Rx-обёртках, работающих через GetStream — собственную реализацию Stream, оптимизированную под Flutter. По бенчмаркам GetX, Rx-переменные в 2-3 раза быстрее ChangeNotifier и в 5-7 раз быстрее BLoC при частых обновлениях (30+ fps). GetX не использует BuildContext для подписок, что исключает перестройку дерева виджетов при навигации.
Best practices: используйте GetBuilder вместо Obx для виджетов с большим количеством дочерних элементов (списки, таблицы). Разделяйте Controller по функциональным модулям, а не один огромный Controller на страницу. Используйте Bindings для инициализации Controller, а не Get.put в build-методе. GetView — сокращённый StatelessWidget с доступом к Controller через controller без Get.find.
Известные ограничения: GetX использует глобальные переменные (Get.find, Get.to), что может затруднить тестирование. Мокинг зависимостей через GetX требует Get.replace() или Get.reset() между тестами. Для изоляции рекомендуется Get.testMode = true. GetX не рекомендуется для приложений, требующих строгой архитектуры с чёткими границами слоёв — в этом случае предпочтительнее BLoC или Riverpod с кодогенерацией.
Часто задаваемые вопросы
GetX — микро-фреймворк со своим DI, навигацией и Rx-реактивностью. Provider — только управление состоянием через ChangeNotifier и InheritedWidget. GetX не требует BuildContext, имеет встроенную навигацию и DI, сокращает boilerplate на 60-70%. Provider использует стандартный Flutter Navigator и требует сторонних решений для DI. GetX быстрее в разработке, Provider — ближе к нативному Flutter API.
Workers — утилиты для реактивной обработки изменений Rx-переменных. ever — колбэк на каждое изменение, once — только на первое, debounce — с задержкой (для поискового поля), interval — не чаще N раз (для аналитики). Workers объявляются в onInit() GetxController и автоматически отписываются в onClose(). Это заменяет ручной addListener/removeListener с ChangeNotifier.
GetX предоставляет Get.testMode = true для включения тестового режима. Зависимости заменяются через Get.replace<Service>(mockService). Между тестами вызывается Get.reset() для очистки DI-контейнера. Controller тестируются напрямую без Flutter: final c = CounterController(); c.increment(); expect(c.count.value, 1). Для виджетов с Obx используйте tester.pumpWidget с InjectMocker.
GetX подходит для проектов любого размера, но требует дисциплины. Для крупных проектов (10+ экранов) используйте: Bindings для изоляции Controller, модули (файлы GetPages на фичу), GetView вместо ручного Get.find в build. Основной риск — злоупотребление глобальным доступом (Get.find в любом месте). Строгие code review и архитектурные гайды решают эту проблему. Многие продакшен-приложения с миллионами пользователей работают на GetX.
Bindings — класс, связывающий маршрут с его зависимостями. При входе на экран Binding создаёт Controller и сервисы через Get.lazyPut, при выходе — удаляет их. Bindings реализуют lazy-инициализацию: Controller не существует в памяти, пока экран не открыт. Это экономит RAM и время старта приложения. Объявляются в GetPage: GetPage(name: '/profile', page: () => ProfileScreen(), binding: ProfileBinding()).
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также