Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
Dizi · 58/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 11 başlık
- Paket mi, Plugin mi? Terim Farkı
- Kendi Paketini Oluşturma
- Plugin Oluşturma — Federated Plugin Mimarisi
- example/ Klasörü — Zorunlu Bir Kanıt
- pub.dev'e Yayınlama
- pubspec.yaml — Metadata
- CHANGELOG.md — Zorunlu Şeffaflık
- Yayınlama Komutları
- Pub Points — pub.dev'in Kalite Skoru
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
Bölüm 1'den beri flutter pub add ile başkalarının yazdığı paketleri kullanıyoruz — http, provider, go_router, camera... Bu derste, madalyonun öbür yüzüne geçiyoruz: kendi paketini yazıp pub.dev'e yayınlamak.
Paket mi, Plugin mi? Terim Farkı
- Paket (package): Sadece saf Dart kodu içerir — örneğin bir string işleme yardımcı kütüphanesi. Platforma özgü hiçbir şey yoktur.
- Plugin: Paketin, native koda (Bölüm 9 Konu 40'ta öğrendiğimiz platform channel'lar aracılığıyla) bağlandığı özel bir türüdür —
camera,geolocatorgibi paketlerin hepsi aslında plugin'dir.
Bu ders, her ikisini de kapsayacak, ama plugin tarafı Konu 40'taki bilgini doğrudan kullanacağın için daha çok oraya odaklanacağız.
Kendi Paketini Oluşturma
flutter create --template=package benim_paketimbenim_paketim/
├── lib/
│ └── benim_paketim.dart # DIŞARIYA açılan tek giriş noktası
├── test/
│ └── benim_paketim_test.dart
├── pubspec.yaml
├── README.md
├── CHANGELOG.md
└── LICENSEBölüm 1 Konu 3'te öğrendiğimiz proje yapısına çok benziyor, ama fark var: bir uygulama (flutter create .) main() fonksiyonuyla çalıştırılabilir; bir paket, başka projelerin import'layacağı, kendi başına çalıştırılamayan bir kütüphanedir (Dart Bölüm 12'de öğrendiğimiz library/export mekanizmasını hatırla).
// lib/benim_paketim.dart
library benim_paketim;
export 'src/hesaplayici.dart'; // Dart Bölüm 12 — hangi dosyaların DIŞARIYA açık olacağını belirlerexport, Dart Bölüm 12'de öğrendiğimiz kritik bir kavram — paketinin lib/src/ altındaki iç detayları (implementasyon), sadece bilinçli olarak export ettiğin kısımlar dışarıdan erişilebilir olur. Bu, Bölüm 7'de öğrendiğimiz Interface Segregation'a benzer bir disiplin: kullanıcına sadece ihtiyacı olanı göster, iç detayları gizle.
Plugin Oluşturma — Federated Plugin Mimarisi
flutter create --template=plugin --platforms=android,ios benim_pluginimModern Flutter plugin'leri, "federated" (dağıtık) bir mimariyle yazılır — Konu 40'ta öğrendiğimiz MethodChannel mantığının, paket seviyesinde organize edilmiş hali:
benim_pluginim/ # ana paket — kullanıcının import ettiği
benim_pluginim_platform_interface/ # SOYUT arayüz (Bölüm 7 Konu 34'teki Dependency Inversion!)
benim_pluginim_android/ # Android implementasyonu
benim_pluginim_ios/ # iOS implementasyonuBunu neden bu kadar parçalıyoruz? Bölüm 7 Konu 34'te öğrendiğimiz Dependency Inversion prensibini hatırla — benim_pluginim_platform_interface, soyut bir sözleşme (tıpkı bir abstract class Repository gibi) tanımlar; _android ve _ios paketleri, bu sözleşmenin somut implementasyonlarıdır. Bu mimarinin büyük faydası: bir üçüncü kişi, senin izin vermene bile gerek kalmadan, kendi benim_pluginim_windows paketini yazıp aynı arayüze uyarak, plugin'ini Windows'a da genişletebilir — tıpkı Bölüm 7'de bir ProfilRepository arayüzüne, senin bilmediğin yeni bir implementasyonun (örn. bir FakeProfilRepository) sorunsuzca eklenebilmesi gibi.
// benim_pluginim_platform_interface/lib/benim_pluginim_platform_interface.dart
abstract class BenimPluginimPlatform extends PlatformInterface {
static BenimPluginimPlatform _instance = MethodChannelBenimPluginim();
static BenimPluginimPlatform get instance => _instance;
Future<String?> platformVersiyonuAl(); // her platformun UYGULAMASI gereken sözleşme
}// benim_pluginim_android/lib/... — Konu 40'taki MethodChannel'ı hatırla!
class MethodChannelBenimPluginim extends BenimPluginimPlatform {
final _kanal = const MethodChannel('benim_pluginim');
@override
Future<String?> platformVersiyonuAl() async {
return await _kanal.invokeMethod<String>('getPlatformVersion');
}
}Basit bir plugin için (tek platform, karmaşık olmayan) bu tam ayrım gerekmez — flutter create --template=plugin komutu, senin ihtiyacına göre daha basit, tek paketli bir yapı da üretebilir. Federated mimari, büyük/topluluk odaklı plugin'ler (birden fazla platformu, birden fazla katkıcıyla desteklemek) için değerlidir.
example/ Klasörü — Zorunlu Bir Kanıt
benim_pluginim/
└── example/
└── lib/main.dart # plugin'i KULLANAN, çalıştırılabilir bir örnek uygulamaHer paket/plugin, kendi içinde bir example/ klasörü barındırmalıdır — bu sadece iyi bir pratik değil, pub.dev'in puanlama sistemi (birazdan göreceğiz) bunu doğrudan ödüllendiriyor. example/, hem senin (paketi geliştirirken gerçek bir uygulamada test etmek için) hem kullanıcıların (paketi nasıl kullanacaklarını çalışan bir kod üzerinden görmek için) işine yarar.
pub.dev'e Yayınlama
pubspec.yaml — Metadata
name: benim_pluginim
description: Cihazın pil seviyesini basitçe okuyan bir Flutter plugin'i.
version: 0.1.0
homepage: https://github.com/kullaniciadi/benim_pluginim
repository: https://github.com/kullaniciadi/benim_pluginim
environment:
sdk: '>=3.0.0 <4.0.0'
flutter: '>=3.10.0'version: 0.1.0 — Konu 53'te öğrendiğimiz semantic versioning kuralları burada da birebir geçerli; 0.x.x sürümü, "henüz kararlı değil, API değişebilir" anlamına gelen bir topluluk kuralıdır (Konu 53'teki 1.0.0'a geçiş, "artık kararlıyım" demenin yoludur).
CHANGELOG.md — Zorunlu Şeffaflık
## 0.1.0
- İlk sürüm: pil seviyesi okuma desteği eklendi.
## 0.1.1
- Android 14 uyumluluğu düzeltildi.Bu, Konu 53'te öğrendiğimiz "sürüm notları" kavramının, paket geliştiricileri için olan versiyonu — bir paketi güncelleyen geliştiricinin, neyin değiştiğini görmesi gerekir. pub.dev, bu dosyanın var olmasını ve güncel tutulmasını bekler.
Yayınlama Komutları
flutter pub publish --dry-run # ÖNCE dene — hataları/uyarıları gerçek yayınlamadan gör
flutter pub publish # gerçekten yayınla — GERİ ALINAMAZ!--dry-run, Bölüm 10 Konu 46'da öğrendiğimiz CI pipeline'ındaki "önce test et, sonra deploy et" disiplinin, paket yayınlama bağlamındaki karşılığı. Kritik uyarı: pub.dev'de bir sürüm yayınlandıktan sonra silinemez (sadece "retract" edilip, "bu sürümü kullanmayın" olarak işaretlenebilir) — bu yüzden --dry-run ile önce doğrulamak zorunludur.
Pub Points — pub.dev'in Kalite Skoru
pub.dev, her paketi otomatik olarak puanlar (0-160 arası, birkaç kategoriye bölünmüş) — bu puan, kullanıcıların hangi paketlere güveneceğine karar vermesinde önemli bir sinyal:
- Dokümantasyon:
README.md'nin kalitesi, her public API'nin doc comment (///) içermesi. - Platform desteği: Kaç platformda (Android/iOS/Web/Windows/macOS/Linux) çalıştığı beyan edilmiş.
- Analiz/statik kontrol: Bölüm 10 Konu 46'da öğrendiğimiz
flutter analyze'ın temiz geçmesi. - Güncel bağımlılıklar:
pubspec.yaml'daki paketlerin güncel sürümlere işaret etmesi (tam da bu tutorial boyunca yaptığımız "güncellik taraması" disiplininin, paket ekosistemi seviyesindeki karşılığı!). example/klasörünün varlığı — yukarıda vurguladığımız gibi.
Pratik gerçek: Bir paket yayınlamadan önce, flutter analyze ve flutter pub publish --dry-run'ı temiz geçirmek, hem kullanıcı güvenini hem pub.dev'deki görünürlüğünü doğrudan etkiler — bu, Bölüm 10'da öğrendiğimiz kalite disiplininin, artık senin sorumluluğun olan bir paket için uygulanmasıdır.
🎯 Bu Dersten Çıkarılması Gerekenler
- Bir "paket", saf Dart kodu içerir; bir "plugin", Bölüm 9 Konu 40'taki platform channel'lar aracılığıyla native koda bağlanır.
lib/paket_adi.dartiçindekiexport'lar, paketin hangi iç detaylarının dışarıya açık olacağını (Interface Segregation'a benzer bir disiplinle) belirler.- Federated plugin mimarisi, Bölüm 7'deki Dependency Inversion prensibini paket seviyesinde uygular — soyut bir
platform_interfacepaketi, her platform için ayrı, bağımsız implementasyon paketleri tarafından karşılanır. example/klasörü hem geliştirme hem pub.dev puanlaması için neredeyse zorunludur.- Yayınlama, semantic versioning (Konu 53) ve güncel
CHANGELOG.mdgerektirir;--dry-runile önce doğrulamak, gerçek yayınlamanın geri alınamaz olması nedeniyle kritiktir. - Pub Points, dokümantasyon, platform desteği, temiz analiz ve güncel bağımlılıklar gibi kriterlere göre otomatik hesaplanır.
📝 Ödevler
- [ ]
flutter create --template=packageile basit bir yardımcı paket oluştur (örn. bir tarih biçimlendirme fonksiyonu),exportile dışarıya aç, en az bir unit test (Bölüm 10 Konu 45) yaz. - [ ] Paketine bir
example/klasörü ekle, paketi gerçekten kullanan çalıştırılabilir bir uygulama yaz. - [ ]
README.mdveCHANGELOG.md'yi doldur,flutter pub publish --dry-runçalıştırıp çıkan uyarıları (varsa) düzelt. - [ ] Kendi cümlelerinle, "federated plugin mimarisinin, Bölüm 7'de öğrendiğimiz Dependency Inversion prensibiyle nasıl aynı fikri paylaştığını" açıkla.
- [ ] pub.dev'deki popüler bir paketin (örn.
httpveyaprovider) sayfasına git, Pub Points bölümünü incele, hangi kriterlerde tam puan aldığını gözlemle.
Sıradaki konu: Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)