↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı

4 dk okuma #flutter
Dizi · 5/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 10 başlık
  1. Widget Nedir? — Dart Bilginle Tam Bir Tanım
  2. "Her Şey" Derken Gerçekten Her Şey
  3. Widget Ağacı — Somut Bir Örnek
  4. child Parametresi — Tek Çocuklu Widget'lar
  5. children Parametresi — Çoklu Çocuklu Widget'lar
  6. Widget'lar Neden immutable (Değişmez)?
  7. build() Metodu — Widget'ın "Ne İstediğini" Tarif Etmesi
  8. Küçük Bir Pratik — Kendi Widget'ını Yazma
  9. 🎯 Bu Dersten Çıkarılması Gerekenler
  10. 📝 Ödevler

Bölüm 2'ye hoş geldin — artık gerçekten kod yazmaya başlıyoruz. Bölüm 1 Konu 1'de kısaca değindiğimiz "her şey widget'tır" felsefesini şimdi derinlemesine işleyeceğiz.

Widget Nedir? — Dart Bilginle Tam Bir Tanım

Bölüm 1'de widget'ları "ekranda bir şeyi tarif eden açıklamalar" olarak tanımlamıştık. Şimdi Dart bilginle daha kesin bir tanım yapalım: her widget, Dart'ta Widget sınıfından türeyen bir class'tır (Dart Bölüm 7'de öğrendiğimiz extends kalıtımı).

dart
import 'package:flutter/material.dart';

class SelamWidget extends StatelessWidget {
  const SelamWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Text('Merhaba Flutter!');
  }
}

Bu, senin kendi yazdığın ilk widget'ın. Dikkat et — bu tamamen tanıdık bir Dart class'ı: extends (Bölüm 7), constructor (Bölüm 6), @override (Bölüm 7), bir metod (build) — hepsi zaten bildiğin kavramlar.

"Her Şey" Derken Gerçekten Her Şey

Flutter'da şaşırtıcı derecede çok şey widget'tır — sadece görsel öğeler değil:

dart
Padding(          // bu bile bir widget! (boşluk ekleme)
  padding: const EdgeInsets.all(16.0),
  child: Text('Merhaba'),
)

Padding, ekranda kendi başına görünmeyen, sadece çocuğuna (child) boşluk ekleyen bir widget'tır. Bu, Flutter'ın felsefesini gösteriyor: layout (yerleşim), stil, davranış — hepsi widget'lar aracılığıyla ifade edilir, ayrı bir "stil dili" veya "layout dili" yoktur. Bölüm 6'da (Dart) öğrendiğimiz kompozisyon ilkesinin, burada UI tasarımına uygulandığını görüyorsun.

Widget Ağacı — Somut Bir Örnek

dart
class OrnekWidget extends StatelessWidget {
  const OrnekWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Container(
          color: Colors.blue,
          child: Text('Merhaba, Flutter!'),
        ),
      ),
    );
  }
}

Bu kod, şu ağacı oluşturuyor:

metin
Center
  └── Padding
        └── Container (mavi renk)
              └── Text('Merhaba, Flutter!')

Her widget'ın tek bir görevi var:

  • Center: çocuğunu ortalar.
  • Padding: çocuğunun etrafına boşluk ekler.
  • Container: bir arka plan rengi (ve başka birçok özellik) sağlar.
  • Text: metni gösterir.

Bu, Dart Bölüm 7'de öğrendiğimiz "her class'ın tek bir sorumluluğu olmalı" (single responsibility) mantığının UI'a uygulanmış hali — büyük, her şeyi yapan tek bir widget yerine, küçük, tek işi yapan widget'ları iç içe geçirerek karmaşık arayüzler kuruyorsun.

child Parametresi — Tek Çocuklu Widget'lar

Yukarıdaki örnekte, her widget'ın bir child parametresi vardı — bu, Dart Bölüm 5'te öğrendiğimiz named parametreler'dir:

dart
Center(
  child: Text('Merhaba'),
)

Center'ın constructor'ı, child adında bir named parametre alıyor (Dart Bölüm 5 Konu 21'i hatırla — {required this.child} gibi bir tanım, aslında Flutter'ın kendi kaynak kodunda böyle yazılmış). Bu widget'lar tek bir çocuk alabilir — o çocuğu "sarmalar" (wrap eder) ve ona bir davranış/stil ekler.

children Parametresi — Çoklu Çocuklu Widget'lar

Bazı widget'lar, birden fazla çocuk alabilir — bu durumda parametre adı children (çoğul) olur ve bir List<Widget> alır (Dart Bölüm 4'ü hatırla!):

dart
Column(
  children: [
    Text('Birinci satır'),
    Text('İkinci satır'),
    Text('Üçüncü satır'),
  ],
)

Column, çocuklarını dikey olarak sıralar (bunu Bölüm 2 Konu 7'de tam olarak işleyeceğiz). Buradaki children: [...], Dart Bölüm 4'te öğrendiğimiz liste literal sözdizimidir — hiçbir yeni şey öğrenmene gerek yok, sadece bir widget'ın parametresi olarak bir liste geçiriyorsun.

Widget'lar Neden immutable (Değişmez)?

Dart Bölüm 2'de final ve const kavramlarını öğrenmiştik. Flutter'da widget'ların hemen tüm alanları final'dır ve widget'ın kendisi genelde const olarak oluşturulabilir:

dart
class MyWidget extends StatelessWidget {
  final String mesaj; // final — Dart Bölüm 6'yı hatırla

  const MyWidget({super.key, required this.mesaj}); // const constructor

  @override
  Widget build(BuildContext context) {
    return Text(mesaj);
  }
}

Neden bu kadar önemli? Bölüm 1 Konu 1'de öğrendiğimiz Widget/Element/RenderObject ayrımını hatırlarsan — widget'lar, "ne isteniyor" açıklamasıdır ve her rebuild'de yeniden oluşturulabilirler (bu, ucuz bir işlemdir çünkü widget'lar hafif nesnelerdir). Değişmez olmaları, Dart Bölüm 13 Konu 62'de öğrendiğimiz const nesnelerin bellek paylaşımı avantajını doğrudan kullanmalarını sağlar — aynı const widget, birden fazla yerde tek bir bellek konumunu paylaşarak kullanılabilir, gereksiz yeniden oluşturmadan kaçınılır.

build() Metodu — Widget'ın "Ne İstediğini" Tarif Etmesi

dart
@override
Widget build(BuildContext context) {
  return Text('Merhaba');
}

Her widget'ın (StatelessWidget veya StatefulWidget, Bölüm 2 Konu 6'da tam olarak göreceğiz) bir build() metodu vardır — bu, Dart Bölüm 7'de öğrendiğimiz override edilen bir metoddur (üst sınıf StatelessWidget'tan geliyor). build()'in görevi, widget ağacının bu parçasının nasıl görünmesi gerektiğini döndürmektir — Flutter, bu metodu gerektiğinde (widget yeniden oluşturulması gerektiğinde) çağırır.

BuildContext context parametresi nedir? Şimdilik, context'i "bu widget'ın ağaçtaki konumu hakkında bilgi taşıyan bir nesne" olarak düşün — Bölüm 4'te (tema, MediaQuery gibi konularda) bunun gerçek gücünü göreceğiz. Şu an sadece build() metodunun her zaman bu parametreyi aldığını bil.

Küçük Bir Pratik — Kendi Widget'ını Yazma

dart
import 'package:flutter/material.dart';

class KarsilamaKarti extends StatelessWidget {
  const KarsilamaKarti({super.key});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Container(
        color: Colors.amber,
        child: Column(
          children: [
            Text('Hoş Geldin!'),
            Text('Flutter öğreniyorsun'),
          ],
        ),
      ),
    );
  }
}

Bu widget, kendi başına yeniden kullanılabilir bir bileşendir — Dart Bölüm 6'da öğrendiğimiz "sınıflar yeniden kullanılabilir yapı taşlarıdır" prensibinin, UI dünyasındaki karşılığı. Bunu, uygulamanın herhangi bir yerinde, KarsilamaKarti() yazarak kullanabilirsin — tıpkı kendi yazdığın bir Dart class'ını başka bir yerde Kisi() diye kullanman gibi.


🎯 Bu Dersten Çıkarılması Gerekenler

  • Her widget, Dart'ta Widget'tan (veya StatelessWidget/StatefulWidget gibi ara sınıflardan) türeyen bir class'tır — Dart'ta öğrendiğin extends, @override, constructor kavramları doğrudan geçerlidir.
  • Widget'lar, tek bir görevi olan küçük parçalar halinde tasarlanır ve iç içe geçirilerek (kompozisyon) karmaşık arayüzler oluşturulur.
  • child (tekil) ve children (List, çoğul) parametreleri, widget'ların nasıl iç içe geçtiğini belirler.
  • Widget'lar genelde immutabledır (final alanlar, const constructor) — bu, performans ve bellek avantajı sağlar (Dart Bölüm 13'ü hatırla).
  • build(BuildContext context), her widget'ın "ne görüneceğini" tarif eden, override edilen bir metoddur.

📝 Ödevler

  • [ ] StatelessWidget'tan türeyen, en az 3 seviye iç içe widget (örn. Center → Padding → Text) içeren kendi widget'ını yaz.
  • [ ] Column ile children parametresine en az 3 Text widget'ı ekleyen bir örnek yaz.
  • [ ] Kendi widget'ının hangi alanlarının final olduğunu belirle, neden final olmaları gerektiğini (Dart Bölüm 6/13 bağlamında) açıkla.
  • [ ] Bir widget'ı, uygulamanın (varsayılan sayaç uygulamasının) içinde iki farklı yerde kullanarak, yeniden kullanılabilirliğini kanıtla.
  • [ ] Kendi cümlelerinle, "Flutter'da neden ayrı bir 'stil dili' yok, her şey widget üzerinden ifade ediliyor" sorusunu, kompozisyon kavramıyla ilişkilendirerek açıkla.

Sıradaki konu: Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + setState() Derinlemesine (Rebuild Mekanizması)