GetX Nedir? Durum Yönetimi, Route ve Bağımlılık Enjeksiyonu (Örneklerle)
GetX, Flutter uygulamalarında durum yönetimi, sayfa geçişleri (route) ve bağımlılık enjeksiyonunu tek pakette toplayan bir kütüphane. pub.dev üzerinde get adıyla yayınlanıyor. Flutter'a yeni başlayanların çoğu önce GetX ile tanışıyor, çünkü az kodla çalışan bir yapı kurmanıza izin veriyor. Bu yazıda üç parçasını da çalışan örneklerle anlatıyorum, sonunda da ne zaman tercih edilmeli, ne zaman başka bir yola bakılmalı onu yazıyorum. Flutter'ı yeni öğreniyorsanız önce Flutter nedir yazısına göz atabilirsiniz.
GetX nedir, neden kullanılır?
Flutter tek başına bir arayüz kütüphanesi. Ekranlar arası geçiş, uygulama genelinde veri paylaşımı ve sınıfların birbirine nasıl verileceği gibi konularda sizi bir yöne zorlamıyor. GetX bu üç konuyu tek çatıda çözüyor:
- Durum yönetimi: Veri değişince ekranın ilgili kısmı kendiliğinden yenilenir.
- Route yönetimi:
BuildContextkullanmadan sayfaya git, geri dön, dialog ve snackbar aç. - Bağımlılık enjeksiyonu: Bir sınıfı bir kez oluştur, uygulamanın her yerinden bul.
Kurulum tek komut:
flutter pub add get
Kurulum ve ilk ayar
GetX'in route ve snackbar gibi özelliklerini kullanmak için uygulamanın kökünde MaterialApp yerine GetMaterialApp kullanılır. Yalnız durum yönetimini kullanacaksanız MaterialApp ile de çalışır.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() => runApp(const Uygulama());
class Uygulama extends StatelessWidget {
const Uygulama({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX Örnek',
home: const SayacSayfasi(),
);
}
}
GetX ile durum yönetimi
İki yaklaşım var: reaktif (Obx) ve basit (GetBuilder). Önce reaktif olanı görelim. Bir değişkenin sonuna .obs eklediğinizde o değişken "gözlemlenebilir" olur. Değiştiğinde Obx içindeki widget yeniden çizilir.
class SayacController extends GetxController {
final sayac = 0.obs;
void artir() => sayac.value++;
}
class SayacSayfasi extends StatelessWidget {
const SayacSayfasi({super.key});
@override
Widget build(BuildContext context) {
final c = Get.put(SayacController());
return Scaffold(
appBar: AppBar(title: const Text('Sayaç')),
body: Center(
child: Obx(() => Text('Tıklama: ${c.sayac.value}')),
),
floatingActionButton: FloatingActionButton(
onPressed: c.artir,
child: const Icon(Icons.add),
),
);
}
}
Burada sayfanın tamamı yeniden çizilmiyor, yalnız Obx içindeki Text güncelleniyor. Liste için RxList de aynı mantıkla çalışır: final urunler = <String>[].obs; tanımlayıp urunler.add('Kalem') dediğinizde liste kendiliğinden yenilenir.
GetBuilder ile basit durum yönetimi
Her değişkeni gözlemlenebilir yapmak istemezseniz update() çağırarak yenilemeyi kendiniz tetikleyebilirsiniz. Bellekte biraz daha hafiftir, ama yenilemeyi çağırmayı unutmamak size kalır.
class SepetController extends GetxController {
final List<String> urunler = [];
void ekle(String ad) {
urunler.add(ad);
update();
}
}
// Ekranda:
GetBuilder<SepetController>(
init: SepetController(),
builder: (c) => Text('Sepette ${c.urunler.length} ürün var'),
)
Controller yaşam döngüsü
GetxController içinde onInit() controller oluşunca, onClose() bellekten atılırken çağrılır. API'den veri çekmek için onInit doğal yerdir, dinlediğiniz akışları kapatmak için de onClose kullanılır.
class UrunController extends GetxController {
final urunler = <String>[].obs;
final yukleniyor = true.obs;
@override
void onInit() {
super.onInit();
verileriGetir();
}
Future<void> verileriGetir() async {
yukleniyor.value = true;
await Future.delayed(const Duration(seconds: 1)); // API çağrısı yerine
urunler.assignAll(['Kalem', 'Defter', 'Silgi']);
yukleniyor.value = false;
}
}
GetX ile route yönetimi
En çok sevilen yanı Navigator.of(context) yazmadan geçiş yapabilmek. İsimli route tanımlamak için getPages kullanılır. Yol parametresi de desteklenir.
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => const AnaSayfa()),
GetPage(name: '/urun/:id', page: () => const UrunDetay()),
],
)
Geçiş ve geri dönüş:
Get.to(() => const UrunDetay()); // sayfayı doğrudan aç
Get.toNamed('/urun/42'); // isimli route ile aç
Get.off(() => const AnaSayfa()); // mevcut sayfayı kapatıp aç
Get.offAllNamed('/'); // geçmişi temizleyip aç
Get.back(); // geri dön
Detay sayfasında yol parametresini şöyle okursunuz:
class UrunDetay extends StatelessWidget {
const UrunDetay({super.key});
@override
Widget build(BuildContext context) {
final id = Get.parameters['id'];
return Scaffold(
appBar: AppBar(title: Text('Ürün $id')),
body: Center(
child: ElevatedButton(
onPressed: Get.back,
child: const Text('Geri'),
),
),
);
}
}
Dialog ve snackbar da context istemez:
Get.snackbar('Kaydedildi', 'Ürün sepete eklendi');
Get.defaultDialog(title: 'Emin misiniz?', middleText: 'Bu işlem geri alınamaz.');
GetX ile bağımlılık enjeksiyonu
Bir sınıfı (servis, controller) bir kez kaydedip her yerden bulma işine bağımlılık enjeksiyonu denir. GetX'te üç temel komut var:
Get.put(...): Nesneyi hemen oluşturur ve kaydeder.Get.lazyPut(() => ...): İlk kullanıldığı anda oluşturur. Açılış süresi için daha iyi.Get.find<T>(): Kayıtlı nesneyi getirir.
class ApiServisi extends GetxService {
Future<List<String>> urunleriGetir() async {
return ['Kalem', 'Defter'];
}
}
void main() {
Get.put(ApiServisi(), permanent: true);
runApp(const Uygulama());
}
// Başka bir yerde:
final api = Get.find<ApiServisi>();
Binding ile sayfaya özel bağımlılık
Controller'ı sayfa açılırken oluşturup sayfa kapanınca bellekten atmak için Binding kullanılır. Böylece sayfa kodunda Get.put yazmazsınız.
class UrunBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<UrunController>(() => UrunController());
}
}
GetPage(
name: '/urunler',
page: () => const UrunListesi(),
binding: UrunBinding(),
)
class UrunListesi extends GetView<UrunController> {
const UrunListesi({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Obx(() => controller.yukleniyor.value
? const Center(child: CircularProgressIndicator())
: ListView(
children: controller.urunler
.map((u) => ListTile(title: Text(u)))
.toList(),
)),
);
}
}
GetView<T>, ilgili controller'a controller adıyla doğrudan erişmenizi sağlayan hazır bir widget'tır.
Sık yapılan hatalar
Obxiçinde gözlemlenebilir değer okumamak.Obxiçinde hiç.obsdeğişkeni okunmazsa Get bunu hata olarak bildirir. Değer.valueile okunmalı.- Her şeyi
permanentyapmak. Kalıcı kayıtlar bellekte kalır. Yalnız gerçekten uygulama boyu lazım olan servisleri kalıcı yapın. - İş mantığını widget'a gömmek. Hesap, API çağrısı ve karar mantığı controller'da olmalı. Widget yalnız göstermeli.
- Kaydı yapılmamış servisi bulmaya çalışmak.
Get.findkayıtsız bir tip için hata verir. Kaydımainya da binding'de yaptığınızdan emin olun.
GetX mi, Riverpod mu, Bloc mu?
Üçü de üretimde kullanılıyor ve doğru cevap ekibe ve projeye göre değişiyor. GetX az kodla hızlı sonuç verir, küçük ve orta ölçekli uygulamalarda ve prototiplerde rahat çalışır. Büyük ekiplerde, katı katman ayrımı ve yüksek test edilebilirlik isteyen projelerde Riverpod ya da Bloc daha disiplinli bir yapı sunar. GetX'in her şeyi tek pakette toplaması kolaylık olduğu kadar bağımlılığı da artırır. Yeni bir projede seçim yaparken paketin güncel bakım durumuna pub.dev'den bakmanızı, ekibin alışık olduğu yapıyı da hesaba katmanızı öneririm.
Benim yaklaşımım, kararı projenin ömrüne ve ekibine göre vermek. Kısa ömürlü bir MVP ile yıllarca sürecek bir kurumsal uygulama aynı mimariyi gerektirmiyor. Flutter'ı başka çatılarla kıyaslayan bir yazı için Flutter mı React Native mi yazısına bakabilirsiniz.
Sık sorulan sorular
GetX öğrenmesi kolay mı?
Evet, temel kullanımı birkaç saatte oturur. Zorluk, proje büyürken klasör yapısını ve controller sınırlarını düzenli tutmakta çıkıyor.
GetX hâlâ kullanılıyor mu?
Evet, pek çok uygulamada kullanılıyor. Yine de her paket için olduğu gibi seçmeden önce pub.dev'deki son sürüm tarihine ve açık sorunlara bakmak doğru bir alışkanlık.
GetX ile Provider arasındaki fark nedir?
Provider yalnız durum paylaşımına odaklanır ve Flutter'ın widget ağacına dayanır. GetX ise route ve bağımlılık enjeksiyonunu da içerir ve BuildContext gerektirmez.
Flutter projeniz için destek
Mimari seçimi, mevcut bir Flutter uygulamasını düzene sokmak ya da sıfırdan yeni bir uygulama geliştirmek için Flutter mobil uygulama hizmetime ve Flutter uygulama geliştirme sayfasına göz atabilirsiniz. Neler yapılabildiğini merak ediyorsanız Flutter ile neler yapılabilir yazısı iyi bir başlangıç. Projenizi kısaca iletişim formundan ya da WhatsApp'tan yazın, kapsama göre kalemli bir teklif paylaşayım.