GetX — lekki mikroframework dla Flutter, łączący zarządzanie stanem, nawigację i wstrzykiwanie zależności w jednym pakiecie. Stworzony przez Amira Hosseina Abdorashidiego, GetX oferuje minimalny boilerplate: bez Stream, bez ChangeNotifier, bez BuildContext do nawigacji. Według danych pub.dev, GetX zdobył ponad 13 tysięcy polubień, stając się jednym z najpopularniejszych pakietów Flutter.
Najważniejsze
GetX — all-in-one mikroframework dla Flutter, rozwiązujący trzy główne zadania programistyczne: zarządzanie stanem (State Management), nawigację (Routing) i wstrzykiwanie zależności (DI). GetX nie wymaga Stream, ChangeNotifier, Builderów ani subskrypcji — całą reaktywność zapewniają Rx-otoczki oparte na GetValue i GetStream, działające kilkadziesiąt razy szybciej niż ChangeNotifier.
GetX pozycjonuje się jako alternatywa dla zestawu Provider + Navigator + get_it/kiwi. Zamiast instalować trzy różne pakiety i pisać 10 linii konfiguracji, GetX daje wszystko z pudełka z jedną linią: GetMaterialApp zamiast MaterialApp. Nawigacja działa przez Get.to(NextScreen()) bez BuildContext, a DI — przez Get.put(Service()) bez drzewa Provider.
Według danych Flutter Community Survey 2025, GetX jest używany w 43% projektów Flutter. Główne powody wyboru: minimalny próg wejścia (5 minut na opanowanie), brak boilerplate (kod skraca się o 60-70% w porównaniu z Provider lub BLoC) i szybkie tworzenie MVP. Krytycy wskazują na naruszenie zasady separacji odpowiedzialności i trudności w debugowaniu.
Obx — reaktywny widżet GetX, przebudowujący się przy zmianie Rx-zmiennych. Obx nie wymaga subskrypcji, dispose ani funkcji Builder — wystarczy owinąć widżet w Obx i użyć wewnątrz Rx-zmiennej. Obx automatycznie śledzi, które Rx-zmienne są używane, i przerysowuje tylko przy ich zmianie.
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-zmienne: .obs — getter, opakowujący dowolną wartość w obiekt Rx. GetX dostarcza typowane klasy Rx: RxInt, RxString, RxDouble, RxBool, RxList, RxMap. Wszystkie Rx-zmienne zachowują się jak zwykłe prymitywy: count++, name.value = 'Hello', items.add(item). Zmiana automatycznie powiadamia subskrybentów Obx.
GetBuilder — alternatywa dla Obx bez Rx, działająca przez ręczne wywołanie update(). GetBuilder.filter — do punktowej aktualizacji po kluczach ID. Obx jest szybszy (automatyczne śledzenie zależności), GetBuilder bardziej przewidywalny (jawne wywołanie aktualizacji). Zaleca się Obx dla prostych scenariuszy i GetBuilder dla złożonych widżetów z wieloma zależnościami.
GetxController — klasa bazowa dla logiki biznesowej z obsługą cyklu życia. GetxController posiada metody: onInit() (inicjalizacja), onReady() (po pierwszej klatce), onClose() (zwalnianie zasobów). W przeciwieństwie do ChangeNotifier i StateNotifier, GetxController automatycznie zarządza subskrypcjami: przy zniszczeniu strony wszystkie Rx-zmienne i Workers są wypisywane.
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 — reaktywne narzędzia GetX: ever (wywoływane przy każdej zmianie), once (tylko przy pierwszej zmianie), debounce (z opóźnieniem), interval (nie częściej niż N razy na sekundę). Workers rozwiązują typowe zadania: walidacja pól (debounce), analityka (once), synchronizacja (ever). Workers są automatycznie wypisywane przy wywołaniu onClose(), zapobiegając wyciekom.
Nawigacja GetX nie wymaga BuildContext do przejścia między ekranami. Zamiast Navigator.push(context, MaterialPageRoute(...)) używa się Get.to(NextScreen()) — wywołanie z dowolnego miejsca, włączając Controller bez dostępu do BuildContext. GetX obsługuje nazwane trasy, animacje, middleware i przekazywanie argumentów bez MaterialPageRoute.
// Zwykła nawigacja
Get.to(ProfileScreen());
Get.back();
Get.off(LoginScreen()); // zastąp bieżącą trasę
Get.offAll(HomeScreen()); // wyczyść stos
// Nazwane trasy
Get.toNamed('/profile', arguments: 'user123');
Get.offNamed('/login');
// Middleware
GetPage(
name: '/profile',
page: () => ProfileScreen(),
middlewares: [AuthMiddleware()],
)GetPage i GetPages: GetX używa GetPages zamiast routes w MaterialApp. Middleware — sprawdzanie autoryzacji, przekierowania, analityka przed wejściem na ekran. Transition — wbudowane animacje przejścia: fadeIn, zoom, leftToRight, topToBottom. Bindings — klasa inicjalizująca Controller i zależności przy wejściu na trasę. Bindings rozwiązują problem leniwej inicjalizacji: Controller jest tworzony tylko gdy ekran jest otwarty.
Get.put — rejestracja instancji w DI-kontenerze. Get.find — pobieranie instancji z kontenera. Get.lazyPut — leniwa inicjalizacja (tworzona przy pierwszym wywołaniu find). Get.putAsync — asynchroniczna inicjalizacja (dla serwisów z init). Get.delete — usuwanie z kontenera (wywoływane automatycznie przez Bindings przy zniszczeniu trasy).
| Metoda | Kiedy tworzona | Kiedy usuwana |
|---|---|---|
| Get.put | Natychmiast | Get.delete lub onClose |
| Get.lazyPut | Przy pierwszym find | Get.delete lub onClose |
| Get.putAsync | Po wykonaniu Future | Get.delete lub onClose |
| Get.create | Przy każdym find (nowa fabryka) | Nie |
GetX DI — najprostszy DI-kontener we Flutter. Brak drzewa Provider, brak Module, brak Scope. Get.put(Repository()) w Controller lub main.dart sprawia, że obiekt jest dostępny w dowolnym miejscu aplikacji przez Get.find<Repository>(). GetX DI obsługuje również tagowanie (tag: 'api') i trwałość (permanent: true) zapobiegającą usunięciu.
Wydajność GetX opiera się na Rx-otoczkach działających przez GetStream — własną implementację Stream zoptymalizowaną pod Flutter. Według benchmarków GetX, Rx-zmienne są 2-3 razy szybsze od ChangeNotifier i 5-7 razy szybsze od BLoC przy częstych aktualizacjach (30+ fps). GetX nie używa BuildContext do subskrypcji, co eliminuje przebudowę drzewa widżetów przy nawigacji.
Best practices: używaj GetBuilder zamiast Obx dla widżetów z dużą liczbą elementów potomnych (listy, tabele). Dziel Controller według modułów funkcjonalnych, a nie jeden ogromny Controller na stronę. Używaj Bindings do inicjalizacji Controller, a nie Get.put w metodzie build. GetView — skrócony StatelessWidget z dostępem do Controller przez controller bez Get.find.
Znane ograniczenia: GetX używa zmiennych globalnych (Get.find, Get.to), co może utrudnić testowanie. Mockowanie zależności przez GetX wymaga Get.replace() lub Get.reset() między testami. Dla izolacji zaleca się Get.testMode = true. GetX nie jest zalecany dla aplikacji wymagających ścisłej architektury z wyraźnymi granicami warstw — w takim przypadku preferowany jest BLoC lub Riverpod z kodogeneracją.
Często zadawane pytania
GetX — mikroframework z własnym DI, nawigacją i Rx-reaktywnością. Provider — tylko zarządzanie stanem przez ChangeNotifier i InheritedWidget. GetX nie wymaga BuildContext, ma wbudowaną nawigację i DI, redukuje boilerplate o 60-70%. Provider używa standardowego Flutter Navigator i wymaga zewnętrznych rozwiązań dla DI. GetX jest szybszy w rozwoju, Provider — bliższy natywnemu Flutter API.
Workers — narzędzia do reaktywnego przetwarzania zmian Rx-zmiennych. ever — callback przy każdej zmianie, once — tylko przy pierwszej, debounce — z opóźnieniem (dla pola wyszukiwania), interval — nie częściej niż N razy (dla analityki). Workers deklaruje się w onInit() GetxController i automatycznie wypisują się w onClose(). Zastępuje to ręczne addListener/removeListener z ChangeNotifier.
GetX dostarcza Get.testMode = true do włączenia trybu testowego. Zależności zastępuje się przez Get.replace<Service>(mockService). Między testami wywołuje się Get.reset() do czyszczenia DI-kontenera. Controller testuje się bezpośrednio bez Flutter: final c = CounterController(); c.increment(); expect(c.count.value, 1). Dla widżetów z Obx używaj tester.pumpWidget z InjectMocker.
GetX nadaje się do projektów każdej wielkości, ale wymaga dyscypliny. Dla dużych projektów (10+ ekranów) używaj: Bindings do izolacji Controller, modułów (pliki GetPages na funkcjonalność), GetView zamiast ręcznego Get.find w build. Główne ryzyko — nadużywanie globalnego dostępu (Get.find w dowolnym miejscu). Rygorystyczne code review i wytyczne architektoniczne rozwiązują ten problem. Wiele produkcyjnych aplikacji z milionami użytkowników działa na GetX.
Bindings — klasa łącząca trasę z jej zależnościami. Przy wejściu na ekran Binding tworzy Controller i serwisy przez Get.lazyPut, przy wyjściu — usuwa je. Bindings implementują leniwą inicjalizację: Controller nie istnieje w pamięci, dopóki ekran nie jest otwarty. Oszczędza to RAM i czas uruchomienia aplikacji. Deklaruje się w GetPage: GetPage(name: '/profile', page: () => ProfileScreen(), binding: ProfileBinding()).
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również