Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
Dizi · 14/61 Flutter Türkçe Tutorial
- Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
- Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
- Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
- Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
- Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
- Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
- Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
- Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
- Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
- Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
- Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
- Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
- Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
- Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
- Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
- Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
- Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
- Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
- Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
- Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
- Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
- Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
- Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
- Bölüm 6 — Konu 24: Provider Paketi
- Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
- Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
- Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
- Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
- Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
- Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
- Bölüm 7 — Konu 31: Deep Linking
- Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
- Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
- Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
- Bölüm 8 — Konu 35: Implicit Animasyonlar
- Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
- Bölüm 8 — Konu 37: Hero Animasyonları
- Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
- Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
- Bölüm 9 — Konu 40: Platform Channels
- Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
- Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
- Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
- Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
- Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
- Bölüm 10 — Konu 46: CI/CD
- Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
- Bölüm 10 — Konu 48: DevTools Profiling
- Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
- Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
- Bölüm 11 — Konu 51: Supabase Alternatifi
- Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
- Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
- Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
- Bölüm 12 — Konu 55: Flutter Web / Desktop
- Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
- Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
- Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
- Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
- Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
- Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
İçindekiler 9 başlık
- Navigator — Bir Yığın (Stack) Olarak Ekranlar
- Navigator.push() — Yeni Bir Ekrana Geçme
- Navigator.pop() — Bir Önceki Ekrana Dönme
- Ekranlar Arası Veri Gönderme
- Named Routes — Yol Tabanlı Navigasyon
- Anonymous vs Named Routes — Ne Zaman Hangisi?
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
- 🏁 Bölüm 3 Tamamlandı!
Bölüm 3'ün son konusundayız. Şimdiye kadar tek ekranlı uygulamalar yazdık — bu derste, ekranlar arası geçişi öğreneceğiz.
Navigator — Bir Yığın (Stack) Olarak Ekranlar
Flutter'da ekranlar arası gezinme, Dart Bölüm 9'da (aslında Bölüm 13'te FFI ile ilişkili olarak Pointer'ı, ama asıl burada ilişkili olan) öğrendiğimiz bir veri yapısına dayanır: yığın (stack). Bunu daha net Dart Bölüm 9 Konu 43'te Kutu<T extends Comparable> gibi generic örneklerde görmüştük ama "stack" kavramının kendisini işlememiştik — kısaca: stack, "son giren ilk çıkar" (LIFO — Last In First Out) mantığıyla çalışan bir veri yapısıdır.
Navigator, tam olarak bunu kullanır: her yeni ekrana geçtiğinde, o ekran yığının üstüne "itilir" (push); geri döndüğünde, en üstteki ekran yığından "çıkarılır" (pop).
Yığın (üstten alta):
[Detay Ekranı] <- şu an görünen (en üstte)
[Ana Ekran]Navigator.push() — Yeni Bir Ekrana Geçme
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetayEkrani()),
);
},
child: Text('Detaya Git'),
)Parça parça inceleyelim:
context— Bölüm 2 Konu 5'te gördüğümüzBuildContext, burada Navigator'a "bu widget'ın ağaçtaki neresinde olduğunu ve hangi Navigator'a ait olduğunu" söylüyor.MaterialPageRoute— yeni ekranın nasıl gösterileceğini tanımlar (Material Design'a uygun geçiş animasyonuyla).builder: (context) => DetayEkrani()— Bölüm 3 Konu 11'de öğrendiğimiz builder pattern'in bir başka örneği! Bir anonim fonksiyon (Dart Bölüm 5), yeni ekranın widget'ını oluşturuyor.
Navigator.pop() — Bir Önceki Ekrana Dönme
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Geri Dön'),
)pop(), yığından en üstteki ekranı çıkarır — kullanıcı, bir önceki ekrana geri döner. Not: AppBar, varsayılan olarak bir "geri" oku otomatik olarak gösterir (eğer Navigator yığınında birden fazla ekran varsa) — bu ok, arka planda zaten Navigator.pop(context) çağırır, sen elle eklemene gerek kalmaz.
Ekranlar Arası Veri Gönderme
1. Giden ekrana veri gönderme (constructor parametreleri ile):
class DetayEkrani extends StatelessWidget {
final String urunAdi;
const DetayEkrani({super.key, required this.urunAdi});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(urunAdi)),
body: Center(child: Text('$urunAdi detayları')),
);
}
}Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetayEkrani(urunAdi: 'Kalem')),
);Bu, Dart Bölüm 6'da öğrendiğimiz constructor parametreleri kavramının doğrudan bir uygulaması — yeni ekranı oluştururken, tıpkı herhangi bir class'ı oluştururken parametre verir gibi veri geçiriyorsun.
2. Geri dönerken veri alma:
// Detay ekranında, geri dönerken bir değer gönderiyoruz
Navigator.pop(context, 'Seçilen Ürün: Kalem');// Ana ekranda, push()'un SONUCUNU bekliyoruz
void _detayaGit() async {
final sonuc = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetayEkrani(urunAdi: 'Kalem')),
);
print('Geri dönen değer: $sonuc');
}Bu, Dart Bölüm 10'da öğrendiğimiz Future/async/await'in doğrudan bir uygulaması! Navigator.push(), aslında bir Future döndürür — bu future, kullanıcı geri dönene kadar tamamlanmaz (Dart Bölüm 10 Konu 45'te öğrendiğimiz "gelecekte bir değer" kavramını hatırla). Kullanıcı Navigator.pop(context, deger) çağırdığında, bu Future o değerle tamamlanır ve await satırı devam eder. Bu, Dart'ı derinlemesine öğrenmenin Flutter'da doğrudan işine yaradığı somut bir andır.
Named Routes — Yol Tabanlı Navigasyon
Yukarıdaki yaklaşım (MaterialPageRoute ile doğrudan widget oluşturma), "anonymous routes" olarak bilinir. Alternatif olarak, her ekrana bir isim vererek, MaterialApp düzeyinde merkezi bir "yol haritası" tanımlayabilirsin:
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => AnaEkran(),
'/detay': (context) => DetayEkrani(),
'/ayarlar': (context) => AyarlarEkrani(),
},
)Bu, Dart Bölüm 4'te öğrendiğimiz Map<String, WidgetBuilder> yapısıdır — anahtar, yol adı ('/detay'); değer, o yolu oluşturan bir builder fonksiyonu.
Named route'a geçiş:
Navigator.pushNamed(context, '/detay');Named route ile veri gönderme (arguments ile):
Navigator.pushNamed(context, '/detay', arguments: 'Kalem');class DetayEkrani extends StatelessWidget {
const DetayEkrani({super.key});
@override
Widget build(BuildContext context) {
final urunAdi = ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
appBar: AppBar(title: Text(urunAdi)),
body: Center(child: Text('$urunAdi detayları')),
);
}
}Dikkat et: arguments, Object? tipinde gelir — bu yüzden as String ile cast etmen gerekiyor (Dart Bölüm 2 Konu 8'de öğrendiğimiz Object ile açık tip dönüşümü kavramını hatırla). Bu, named routes'un doğrudan constructor parametresi yaklaşımına göre daha az tip güvenli olduğu bir noktadır — bu yüzden, Bölüm 3 Konu 14'te (Flutter müfredatının ileri kısmında, Bölüm 7'de) öğreneceğimiz go_router gibi paketler, bu tip güvenliği sorununu çözen daha modern bir yaklaşım sunar.
Anonymous vs Named Routes — Ne Zaman Hangisi?
Anonymous (Navigator.push + MaterialPageRoute) |
Named (Navigator.pushNamed) |
|
|---|---|---|
| Tip güvenliği | ✅ Yüksek (constructor parametreleri) | ⚠️ Düşük (arguments, cast gerektirir) |
| Merkezi yol haritası | ❌ Yok | ✅ Var (routes: {}) |
| Deep linking desteği | ⚠️ Zayıf | ✅ Daha uygun |
| Küçük projeler için | ✅ Basit ve yeterli | Gereksiz karmaşıklık olabilir |
Pratik tavsiye: Küçük/orta projelerde, anonymous routes (tip güvenliği için) genelde tercih edilir. Named routes, uygulaman büyüdükçe ve URL benzeri bir yapıya (özellikle web için) ihtiyaç duyduğunda daha değerli hale gelir. Bölüm 7'de (Flutter müfredatı), go_router ile bu iki yaklaşımın en iyi yönlerini birleştiren modern bir çözümü göreceğiz.
🎯 Bu Dersten Çıkarılması Gerekenler
Navigator, ekranları bir stack (yığın) olarak yönetir —pushile üste eklenir,popile çıkarılır.Navigator.push(), birFuturedöndürür —Navigator.pop(context, deger)ile bu future'ı bir değerle tamamlayabilirsin (Dart'takiFuture/awaitbilginin doğrudan uygulaması).- Ekranlara veri, constructor parametreleriyle (anonymous routes, tip güvenli) veya
argumentsile (named routes, cast gerektirir) gönderilebilir. MaterialApp'inroutes:haritası,Map<String, WidgetBuilder>kullanır — merkezi bir "yol haritası" tanımlamanı sağlar.
📝 Ödevler
- [ ] İki ekranlı bir uygulama yap: ana ekrandan "Detay" ekranına
Navigator.pushile geç. - [ ] Detay ekranına, constructor parametresiyle bir veri (örn. bir isim) gönder, ekranda göster.
- [ ] Detay ekranında geri dönerken,
Navigator.pop(context, deger)ile bir veri döndür, ana ekrandaawaitile bu veriyi al ve yazdır. - [ ] Aynı iki ekranlı yapıyı,
routes:haritası veNavigator.pushNamedkullanarak yeniden yaz. - [ ] Named route ile bir
argumentsgönder,ModalRoute.of(context)!.settings.argumentsile al veasile cast et.
🏁 Bölüm 3 Tamamlandı!
Gerçek bir uygulama iskeleti kurmayı (MaterialApp/Scaffold/AppBar), listeleri (ListView.builder), kendi custom widget'larını tasarlamayı ve ekranlar arası navigasyonu öğrendin. Artık çok ekranlı, gezinebilir bir uygulama yazabiliyorsun.
Sıradaki durak Bölüm 4 — Kullanıcı Girdisi & Tema: form alanları, validasyon, tema sistemi ve responsive tasarım ile devam edeceğiz.