↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)

4 dk okuma #flutter
Dizi · 57/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 8 başlık
  1. Skia Nedir? Neden Yetmedi?
  2. Impeller — Flutter Ekibinin Kendi Motoru
  3. Impeller'ın Güncel Durumu
  4. Render Pipeline'ı Uçtan Uca — UI Thread'den Ekrana
  5. Bunu Neden Bilmen Gerekiyor? — Pratik Faydaları
  6. Bu Bilgiyi Ne Zaman Kullanırsın?
  7. 🎯 Bu Dersten Çıkarılması Gerekenler
  8. 📝 Ödevler

Bölüm 1 Konu 1'den beri "Flutter, kendi piksellerini Skia/Impeller ile çizer" diyoruz ama bunun ne anlama geldiğine hiç girmedik. Bu ders, o cümlenin arkasındaki motoru — ve Flutter ekibinin neden Skia'dan Impeller'a geçtiğini — açıyor.

Skia Nedir? Neden Yetmedi?

Skia, Google'ın geliştirdiği, 2D grafik çizim kütüphanesidir — Chrome, Android'in kendisi ve (uzun süre) Flutter, hepsi Skia kullanır. Flutter'ın Bölüm 8 Konu 38'de öğrendiğimiz Canvas/Paint API'si, doğrudan Skia'nın API'sinin Dart'a taşınmış halidir.

Sorun neydi? Skia, çizim komutlarını (bir dikdörtgen çiz, bir gölge ekle, bir metin yaz), çalışma zamanında, GPU'nun anlayacağı shader (gölgeleme) programlarına derler. Bu derleme, ilk kez karşılaşılan bir görsel efekt kombinasyonu için pahalı bir işlemdir — ve tam da bir animasyon ortasında, ilk kez karşılaşılan bir efekt (örn. yeni bir renk geçişi, yeni bir gölge şekli) tetiklendiğinde gerçekleşebilir. Bu, Bölüm 10 Konu 48'de öğrendiğimiz "jank" (kare bütçesini aşma) kavramının en sinsi sebeplerinden biriydi: "shader compilation jank" — kod tarafında hiçbir hata olmasa bile, bir animasyon ilk kez çalıştığında tek seferlik bir kasma yaşanırdı.

Impeller — Flutter Ekibinin Kendi Motoru

Impeller, Flutter ekibinin, Skia'nın shader derleme sorununu temelden çözmek için sıfırdan yazdığı yeni render motorudur. Temel fikir:

"Derleme zamanında derle, çalışma zamanında değil." Impeller, uygulamanın kullanabileceği tüm shader'ları, flutter build sırasında (Bölüm 9 Konu 44'ü hatırla — AOT derleme ile aynı felsefe) önceden derler. Çalışma zamanında, GPU'ya zaten hazır shader'lar gönderilir — bu, ilk karşılaşılan efektte yaşanan o beklenmedik kasmayı, tasarım gereği ortadan kaldırır.

metin
Skia:      Uygulama çalışıyor → "bu efekti ilk kez görüyorum" → ŞİMDİ shader derle → KASMA
Impeller:  flutter build sırasında → TÜM shader'lar önceden derlenir → çalışırken sadece KULLAN

Impeller'ın Güncel Durumu

Bu, tam da senin "güncelliğe dikkat" istediğin türden bir bilgi — Impeller'ın durumu, Flutter'ın son birkaç sürümünde hızla değişti:

  • iOS'ta, Impeller varsayılan motor olalı uzun süre oldu — Metal (Apple'ın grafik API'si) üzerine inşa edilmiştir.
  • Android'de, Impeller önce OpenGL ES üzerinden, sonra Vulkan (daha modern, daha düşük seviye bir grafik API'si) backend'iyle kademeli olarak varsayılan hale getirildi — bugün itibarıyla çoğu Android cihazda varsayılan motor Impeller'dır; Vulkan'ı desteklemeyen çok eski cihazlarda Skia'ya otomatik olarak geri düşülür (fallback).
  • Web'de, Konu 55'te öğrendiğimiz gibi hâlâ CanvasKit/Skwasm (Skia tabanlı) kullanılıyor — Impeller şu an öncelikli olarak mobil/masaüstü için geliştiriliyor.

Pratik sonuç: Bugün yeni bir Flutter projesi oluşturduğunda, elle hiçbir şey seçmene gerek kalmadan, mobilde Impeller kullanıyor olacaksın — bu artık istisna değil, varsayılan. Eski forum yazılarında/StackOverflow cevaplarında göreceğin "Impeller'ı --enable-impeller ile aç" gibi talimatlar, artık gerekli değil (bazı eski Flutter sürümlerinde geçerliydi).

Render Pipeline'ı Uçtan Uca — UI Thread'den Ekrana

Bölüm 10 Konu 48'de UI thread ile raster thread ayrımını görmüştük — şimdi aradaki tam akışı tamamlayalım:

metin
1. UI THREAD:
   setState() → build() (Widget) → layout/paint (RenderObject, Konu 56) → bir "Scene" (Layer ağacı) oluşturulur

2. RASTER THREAD (Impeller/Skia çalışır):
   Scene → GPU'ya gönderilecek gerçek komutlara çevrilir → GPU pikselleri boyar

3. GPU:
   Piksel piksel ekrana çizilir

Impeller'ın devreye girdiği yer, tam olarak 2. adımdır — Konu 56'da öğrendiğimiz RenderObject.paint() metodu, aslında Impeller'a/Skia'ya verilecek komutları (bir "Layer ağacı" olarak) üretir; Impeller'ın işi, bu komutları GPU'nun anlayacağı hale (önceden derlenmiş shader'ları kullanarak) getirmektir.

Bunu Neden Bilmen Gerekiyor? — Pratik Faydaları

1. Performans sorunlarını doğru teşhis etme: Bölüm 10 Konu 48'de "raster thread yavaş" dediğimizde, artık neyin yavaş olduğunu biliyorsun — Impeller'ın (ya da eski Skia'nın) GPU'ya komut çevirme işi. Eğer çok fazla katman/efekt (Bölüm 10 Konu 49'da RepaintBoundary tartışmasını hatırla) üst üste biniyorsa, bu motor ne kadar hızlı olursa olsun yavaşlar.

2. Eski kaynakları doğru yorumlama: İnternette Flutter performansı hakkında okuyacağın 2023 öncesi birçok makale, "shader jank" sorununu merkez alır — bu makaleleri okurken, bugünkü Impeller varsayılan dünyada bu sorunun büyük ölçüde çözüldüğünü bilerek okumalısın; bazı eski "workaround"lar (elle shader warm-up teknikleri gibi) artık gereksiz olabilir.

3. Platform farklarını anlama: Web'in hâlâ Skia tabanlı (CanvasKit) olması, Konu 55'te öğrendiğimiz "web'in mobilden biraz farklı bir dünya olduğu" gerçeğinin bir başka boyutu — aynı widget kodu, farklı motorlar üzerinden render ediliyor.

Bu Bilgiyi Ne Zaman Kullanırsın?

Dürüst olmak gerekirse: Günlük Flutter geliştirmede, Impeller/Skia ayrımını düşünmene gerek kalmaz — bu, çerçevenin senin için hallettiği bir detaydır. Bu bilgi, şu durumlarda değerli hale gelir: (a) karmaşık, çok katmanlı görsel efektler (Bölüm 8'de öğrendiğimiz CustomPainter, birden fazla ShaderMask/BackdropFilter gibi) içeren bir ekranda beklenmedik yavaşlıkla karşılaştığında, (b) Flutter'ın GitHub issue'larını veya resmi performans dokümantasyonunu okurken "raster thread", "shader compilation" gibi terimlerle karşılaştığında, ya da (c) bir mülakatta ya da teknik tartışmada, "Flutter nasıl çizim yapıyor?" sorusuna yüzeysel değil, gerçek bir cevap vermen gerektiğinde.


🎯 Bu Dersten Çıkarılması Gerekenler

  • Skia, çizim komutlarını çalışma zamanında shader'lara derler — bu, ilk kez karşılaşılan efektlerde "shader compilation jank" adı verilen beklenmedik kasmalara yol açıyordu.
  • Impeller, tüm shader'ları derleme zamanında (AOT ile birlikte) önceden derleyerek bu sorunu tasarım gereği ortadan kaldırır.
  • Bugün itibarıyla Impeller, iOS'ta ve çoğu Android cihazda varsayılan motordur; web hâlâ Skia tabanlı (CanvasKit/Skwasm) çalışır.
  • Render pipeline: UI thread'de build()/layout()/paint() bir Scene üretir → raster thread'de Impeller/Skia bunu GPU komutlarına çevirir → GPU ekrana çizer.
  • Bu bilgi günlük geliştirmede görünmez kalır, ama karmaşık görsel efekt performansı, eski kaynakları doğru yorumlama ve derin teknik tartışmalarda değerlidir.

📝 Ödevler

  • [ ] Bir Flutter projesinde hangi render motorunun aktif olduğunu (Impeller/Skia), flutter run çıktısında veya DevTools'ta (Konu 48) nasıl doğrulayabileceğini araştır ve dene.
  • [ ] Kendi cümlelerinle, "shader compilation jank"in neden özellikle bir animasyonun ilk çalıştırılışında ortaya çıktığını açıkla.
  • [ ] Flutter'ın resmi performans dokümantasyonunda Impeller ile ilgili bir sayfa bul, orada bahsedilen en az bir teknik terimi (örn. "Vulkan backend") araştırıp bir cümleyle özetle.
  • [ ] Bölüm 10 Konu 48'de öğrendiğin "raster thread" kavramını, bu dersteki render pipeline şemasıyla birleştirerek, bir kare çiziminin UI thread'den GPU'ya kadar tüm yolculuğunu kendi cümlelerinle anlat.

Sıradaki konu: Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama