↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)

4 dk okuma #flutter
Dizi · 29/61 Flutter Türkçe Tutorial
  1. Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
  2. Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
  3. Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
  4. Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
  5. Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
  6. Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
  7. Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
  8. Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
  9. Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
  10. Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
  11. Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
  12. Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
  13. Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
  14. Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
  15. Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
  16. Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
  17. Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
  18. Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
  19. Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
  20. Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
  21. Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
  22. Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
  23. Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
  24. Bölüm 6 — Konu 24: Provider Paketi
  25. Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
  26. Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
  27. Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
  28. Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
  29. Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
  30. Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
  31. Bölüm 7 — Konu 31: Deep Linking
  32. Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
  33. Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
  34. Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
  35. Bölüm 8 — Konu 35: Implicit Animasyonlar
  36. Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
  37. Bölüm 8 — Konu 37: Hero Animasyonları
  38. Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
  39. Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
  40. Bölüm 9 — Konu 40: Platform Channels
  41. Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
  42. Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
  43. Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
  44. Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
  45. Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
  46. Bölüm 10 — Konu 46: CI/CD
  47. Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
  48. Bölüm 10 — Konu 48: DevTools Profiling
  49. Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
  50. Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
  51. Bölüm 11 — Konu 51: Supabase Alternatifi
  52. Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
  53. Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
  54. Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
  55. Bölüm 12 — Konu 55: Flutter Web / Desktop
  56. Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
  57. Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
  58. Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
  59. Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
  60. Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
  61. Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
Dizinin sayfası →
İçindekiler 9 başlık
  1. Navigator 1.0'ın Sınırlaması — Neden Navigator 2.0 Var?
  2. Üç Ana Bileşen
  3. 1. RouteInformationParser — URL'yi "Anlamlı Veriye" Çevirme
  4. 2. RouterDelegate — "Şu Anki Duruma Göre Hangi Ekranları Göstermeli?"
  5. 3. MaterialApp.router — Hepsini Birleştirme
  6. Neden Bu Kadar Karmaşık Görünüyor?
  7. Navigator 1.0 vs Navigator 2.0 — Ne Zaman Hangisi?
  8. 🎯 Bu Dersten Çıkarılması Gerekenler
  9. 📝 Ödevler

Bölüm 7'ye hoş geldin. Bu ders, Flutter'ın en karmaşık konularından birine giriyor — dürüst olmak gerekirse, bu dersten sonra öğreneceğin go_router paketi, günlük geliştirmede çok daha sık kullanacağın araç olacak. Ama Navigator 2.0'ın temel mantığını anlamak, go_router'ın neden var olduğunu ve nasıl çalıştığını kavraman için değerli.

Bölüm 3 Konu 14'te öğrendiğimiz Navigator.push()/pop() (buna "Navigator 1.0" denir), zorunlu (imperative) bir yaklaşımdır — sen adım adım, "şimdi şu ekrana git" diyorsun. Bu, basit uygulamalarda gayet iyi çalışır, ama şu senaryolarda zayıf kalır:

  1. Web'de URL senkronizasyonu — Bir web tarayıcısında, kullanıcı geri/ileri tuşlarını kullandığında, ya da doğrudan bir URL'ye giriş yaptığında, uygulamanın doğru ekranı göstermesi gerekir. Navigator 1.0'ın "adım adım push/pop" mantığı, bunu doğal olarak desteklemez.
  2. Deep linking — Bir bildirime tıklandığında, uygulamayı doğrudan belirli bir ekrana (örneğin bir ürün detayına) açmak, Navigator 1.0'da karmaşık, elle yönetilen bir süreç gerektirir.

Navigator 2.0, bunun yerine bildirimsel (declarative) bir yaklaşım sunar — Dart Bölüm 13 Konu 59'da öğrendiğimiz pattern matching'in felsefesine benzer bir mantık: "şu anki durum bu, Flutter sen anla nasıl gösterileceğini."

Üç Ana Bileşen

Navigator 2.0, üç ana parçadan oluşur — bunları kavramsal olarak anlayalım (elle tam bir implementasyon yazmak, gerçekten nadiren gerekir, go_router bunu senin için yapar).

1. RouteInformationParser — URL'yi "Anlamlı Veriye" Çevirme

dart
class UygulamaRotaAyristirici extends RouteInformationParser<UygulamaRotaKonfigurasyonu> {
  @override
  Future<UygulamaRotaKonfigurasyonu> parseRouteInformation(RouteInformation routeInformation) async {
    final uri = routeInformation.uri;
    if (uri.pathSegments.isEmpty) {
      return UygulamaRotaKonfigurasyonu.anaSayfa();
    }
    if (uri.pathSegments[0] == 'urun') {
      final id = uri.pathSegments[1];
      return UygulamaRotaKonfigurasyonu.urunDetay(id);
    }
    return UygulamaRotaKonfigurasyonu.bilinmeyen();
  }
}

Bu, Dart Bölüm 7'de öğrendiğimiz extends ile Flutter'ın kendi soyut sınıfından (Bölüm 7 Konu 34'ü hatırla — soyut sınıflar bir "sözleşme" tanımlar) türetilmiş bir class. Görevi, bir URL string'ini (/urun/123 gibi), uygulamanın anlayacağı bir Dart nesnesine (UygulamaRotaKonfigurasyonu) çevirmek — tıpkı Bölüm 5 Konu 21'de öğrendiğimiz fromJson()'un, JSON'u bir Dart nesnesine çevirmesi gibi bir dönüşüm işlemi.

2. RouterDelegate — "Şu Anki Duruma Göre Hangi Ekranları Göstermeli?"

dart
class UygulamaRouterDelegate extends RouterDelegate<UygulamaRotaKonfigurasyonu>
    with ChangeNotifier { // Dart Bölüm 7'de öğrendiğimiz MIXIN, Bölüm 6'da gördüğümüz ChangeNotifier!

  UygulamaRotaKonfigurasyonu _konfigurasyon = UygulamaRotaKonfigurasyonu.anaSayfa();

  @override
  Widget build(BuildContext context) {
    return Navigator(
      pages: [
        MaterialPage(child: AnaEkran()),
        if (_konfigurasyon.urunId != null)
          MaterialPage(child: UrunDetayEkrani(id: _konfigurasyon.urunId!)),
      ],
      onDidRemovePage: (page) {
        _konfigurasyon = UygulamaRotaKonfigurasyonu.anaSayfa();
        notifyListeners();
      },
    );
  }
  // ... diğer zorunlu metodlar
}

Çok önemli bir gözlem: with ChangeNotifier — Bölüm 6 Konu 24'te öğrendiğimiz ChangeNotifier, burada state management dışında, navigasyon durumunu yönetmek için de kullanılıyor! Bu, Bölüm 7 Konu 36'da (Dart) öğrendiğimiz mixin'in gerçek bir Flutter kullanımı.

pages: [...] — Bu, Navigator 1.0'ın "push/pop" mantığından temel bir sapma: burada sen, "o anki state'e göre hangi sayfaların yığında (stack) olması gerektiğini" bir liste olarak bildiriyorsun — Dart Bölüm 4'te öğrendiğimiz List<Widget> (burada List<Page>) mantığı. Flutter, bu listeyi önceki listeyle karşılaştırıp (Bölüm 1 Konu 1'de öğrendiğimiz diffing mekanizmasına benzer), hangi sayfaların eklenip/çıkarılacağına kendisi karar verir.

3. MaterialApp.router — Hepsini Birleştirme

dart
MaterialApp.router(
  routerDelegate: UygulamaRouterDelegate(),
  routeInformationParser: UygulamaRotaAyristirici(),
)

Bölüm 3 Konu 10'da öğrendiğimiz MaterialApp(home: ...) yerine, MaterialApp.router(...) — Dart Bölüm 6 Konu 27'de öğrendiğimiz named constructor kalıbının, Flutter'ın kendi framework'ünde gerçek bir kullanımı! MaterialApp.router, MaterialApp'in navigasyonu Navigator 2.0'a devreden alternatif bir oluşturma yoludur.

Neden Bu Kadar Karmaşık Görünüyor?

Bu üç bileşeni elle yazmak, dürüst olmak gerekirse, çok fazla "boilerplate" (tekrarlayan, zorunlu) kod gerektirir — zorunlu metodları implemente etmek, state senkronizasyonunu elle yönetmek gibi. Bu tam olarak Bölüm 7 Konu 30'da öğreneceğin go_router'ın var olma sebebidir — go_router, Navigator 2.0'ın gücünü (bildirimsel navigasyon, web URL desteği, deep linking) korurken, bu karmaşıklığı büyük ölçüde gizler.

Navigator 1.0 (push/pop) Navigator 2.0 (Router API)
Öğrenme eğrisi Düşük Yüksek (elle yazarsan)
Mobil-öncelikli, basit uygulamalar ✅ Yeterli ve pratik Gereksiz karmaşıklık
Web desteği (URL senkronizasyonu) ⚠️ Zayıf ✅ Güçlü
Deep linking ⚠️ Elle, karmaşık ✅ Doğal destek
Elle yazmak pratik mi? ✅ Evet ❌ Genelde hayır, go_router tercih edilir

Pratik gerçek: Bugün, Navigator 2.0'ı tamamen elle yazan geliştirici nadirdir — bunun yerine, hemen herkes go_router (veya benzer bir paket) kullanır. Bu dersin amacı, go_router'ı kullanırken "arka planda ne oluyor" sorusuna cevap verebilmen ve karşılaştığın hataları (özellikle web/deep linking ile ilgili) daha derinlemesine anlayabilmendir.


🎯 Bu Dersten Çıkarılması Gerekenler

  • Navigator 1.0, zorunlu (imperative) "adım adım" navigasyon sunar; web URL senkronizasyonu ve deep linking'de zayıf kalır.
  • Navigator 2.0, bildirimsel (declarative) bir yaklaşımla, "o anki state'e göre hangi sayfalar gösterilmeli" mantığıyla çalışır.
  • RouteInformationParser, bir URL'yi anlamlı bir Dart nesnesine çevirir; RouterDelegate, bu nesneye göre hangi sayfaların gösterileceğine karar verir ve ChangeNotifier mixin'ini kullanır.
  • MaterialApp.router, bu ikisini birleştiren named constructor'dır.
  • Navigator 2.0'ı elle yazmak yoğun boilerplate gerektirir — pratikte neredeyse herkes go_router gibi bir paket kullanır (bir sonraki dersimiz).

📝 Ödevler

  • [ ] Kendi cümlelerinle, "Navigator 1.0'ın push/pop mantığı ile Navigator 2.0'ın bildirimsel yaklaşımı arasındaki temel felsefe farkını" açıkla.
  • [ ] RouteInformationParser'ın görevini, Dart'ta öğrendiğimiz fromJson() kalıbıyla karşılaştırarak açıkla.
  • [ ] RouterDelegate'in neden ChangeNotifier kullandığını, Bölüm 6'da öğrendiğin state management bilgisiyle ilişkilendir.
  • [ ] Basit bir RouteInformationParser taslağı yaz (en az 2 farklı URL yolu ayrıştıran), çalıştırmana gerek yok, sadece mantığı pratik et.
  • [ ] Kendi cümlelerinle, "neden pratikte çoğu geliştirici Navigator 2.0'ı elle yazmak yerine go_router kullanıyor" sorusuna cevap ver.

Sıradaki konu: Bölüm 7 — Konu 30: go_router Paketi (Pratik ve Modern Çözüm)