• 29.10.2026 05:24:20
  • İbrahim Gökyar

Bu makalede Flutter mobil uygulama geliştirme için deferred yükleme, AOT snapshot ve tree-shaking ile başlatma süresi ve çalışma zamanı bellek maliyetini nasıl ölçüp düşüreceğinizi adım adım gösteriyorum. Dart programlama eğitimi içeriğiyle pratik örnekler var.

Flutter derin optimizasyon: deferred yükleme, AOT snapshot ve tree-shake

Deferred import ile uygulama başlangıcını geciktirme (flutter mobil uygulama geliştirme)

Deferred import, ağır modülleri uygulama başlatmasından sonra yükleyerek ilk yükleme süresini azaltır. Ölçüm adımı olarak önce cihazda profil modunda başlangıç süresini kaydedin: `flutter run --profile -d --trace-startup` ve DevTools Performance -> Startup trace'i kaydedin; optimizasyondan sonra aynı komutu tekrar çalıştırıp trace'i karşılaştırın. Somut kod:

import 'heavy_feature.dart' deferred as heavy;

Future openHeavyFeature() async {
  // loadLibrary() gerçek kod bytes'ını ve AOT snapshot parçalarını bağlar
  await heavy.loadLibrary();
  heavy.launch();
}
Neden: Dart AOT snapshot'ı ne kadar az kod içerirse, ilk belleğe yüklenen kod ve relocation maliyeti o kadar azalır; bunun sonucu olarak startup'ta I/O ve instruction cache yükü düşer. Edge case: deferred kütüphaneler içindeki top-level side-effect'ler loadLibrary çağrılana dek çalışmaz; bunun önceden bilinmesi gerekiyor. Android tarafında gerçek 'install-time' yerine 'play store dynamic feature' ile paketleme gerekiyorsa CI konfigürasyonuna dynamic-feature Gradle adımı ekleyin (Android Dynamic Feature workflow'u).

AOT snapshot, tree shaking ve gereksiz paketlerin tespiti

Binary ve AOT içeriğini analiz etmek için `flutter build apk --release --analyze-size` çalıştırın; çıktıdaki JSON ve link size hangi paketlerin yer kapladığını gösterir. Örnek kullanım: `flutter build apk --release --analyze-size` komutunu çalıştırın, çıktıdaki analiz linkini açın veya `build/flutter_analysis_*.json` dosyasını inceleyin. Fazla korunmuş entry-point'leri önlemek için reflection veya platform channel ile çağrılan statik fonksiyonlara @pragma('vm:entry-point') ekleyin; aksi halde tree-shaker onları silebilir ve çalışma zamanı hatası oluşturur. Somut kod:

@pragma('vm:entry-point')
class NativeBridge {
  @pragma('vm:entry-point')
  static void onNativeCall(String payload) {
    // platform channel'dan çağrılabilir
  }
}
Neden: tree-shaking, kullanılmadığı kesinleşen kodu kaldırır; ancak native kod veya reflection tarafından referanslanan üyeler tree-shaker tarafından tespit edilemez, bu nedenle explicit entry-point işareti gereklidir. Pratik ipucu: `pubspec.yaml` içinde gereksiz locale veya asset'leri kaldırarak AOT snapshot'ın küçülmesini sağlayın (örneğin l10n'da sadece lazım olan locale'leri belirtin).

Isolate ve TransferableTypedData ile heap churn ve kopyaları azaltma

Büyük byte buffer'ları ana izole üzerinde kopyalamak yerine TransferableTypedData ile izole'lar arası transfer ederek O(n) kopya maliyetini O(1) materyalize etmeye taşıyın. Profiling: `flutter run --profile` çalıştırıp DevTools -> Memory -> Allocation Profile altında GC ve allocation snapshot'larını 30s boyunca kaydedin; optimizasyondan sonra kaydı tekrarlayıp toplam allocation count ve peak heap'i karşılaştırın. Somut kod örneği:

import 'dart:isolate';
import 'dart:typed_data';

Future runDecoder(Uint8List bytes) async {
  final ReceivePort rp = ReceivePort();
  final ttd = TransferableTypedData.fromList([bytes]);
  await Isolate.spawn(_entry, [rp.sendPort, ttd]);
  final result = await rp.first; // isolate'tan gelen sonuç
}

void _entry(List args) {
  final SendPort send = args[0];
  final TransferableTypedData ttd = args[1];
  final Uint8List buf = ttd.materialize().asUint8List();
  // ağır decoding işlemi burada
  send.send('ok');
}
Neden: TransferableTypedData, belleği kopyalamadan ownership transfer eder; normal paylaşımda dart GC her ana buffer için yeni nesneler yaratıp kısa ömürlü atık üretir, bu da GC frekansını ve jank'i artırır. Edge case: TransferableTypedData.materialize() yalnızca tek sefer materyalize edildiğinde sıfırlama politikası gerektirebilir; tekrar paylaşım gerekiyorsa yeni TransferableTypedData oluşturun.

State management ile lazy init: flutter state management ve deferred birlikte kullanma

State yönetiminizi seçerken (Provider, Riverpod, Bloc vb.) ağır bağımlılıkları lazy-initialize edin ki uygulama başında nesneler örneklenmesin. Ölçüm önerisi: kullanıcı açılış ekranında UI rebuild count ve build sürelerini ölçün (DevTools -> Performance -> Frame rendering). Riverpod ile deferred import örneği:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'heavy_feature.dart' deferred as heavy;

final heavyProvider = FutureProvider.autoDispose((ref) async {
  await heavy.loadLibrary();
  return heavy.createService();
});

// UI tarafı
final result = ref.watch(heavyProvider);
Neden: FutureProvider.autoDispose, kullanılmadığında service objesini serbest bırakır; deferred yükleme ise createService() çağrıldığında sınıf kodunu getirir. Pratik hata: lazy init yapılırken UI tetikleyicileri yanlış yerde (build içinde) başlatılırsa sürekli loadLibrary çağrısı tetiklenebilir - bunun yerine onPressed veya initState içinde başlatın ve Future'ı state'e bağlayın.

Profiling workflow ve A/B karşılaştırması: komutlar, script ve metrikler

Ölçülebilir A/B karşılaştırması için otomatik script kullanın. Örnek Android cold-start ölçümü için bir basit bash:

# baseline_launch.sh
flutter build apk --release
adb uninstall com.example.app || true
adb install build/app/outputs/flutter-apk/app-release.apk
adb shell am start -W -n com.example.app/.MainActivity | tee launch_baseline.txt
# sonra optimized sürüm için aynı adımlar tekrarlanır
CPU ve frame profili için: `flutter run --profile -d ` sonra DevTools -> CPU Profiler ile 15s kayıt alıp exported trace'i karşılaştırın. Ölçütler: cold-start totalTime (adb output), first-frame zaman, 90. persentil frame build time. Optimize etmeden önce ve sonra bu metrikleri CSV'ye yazın ve yüzde değişimi hesaplayın. Konfig değişikliği örneği: sık rebuild üreten widget'larda const constructor kullanımıyla rebuild maliyetini düşürün; örnek değişiklik:
// önce
Widget build(BuildContext c) => Text('${user.name}');

// sonra (eğer sabitse)
const Text('Giriş bekleniyor');
Bu otomasyon ve ölçüm adımları, optimizasyonun gerçekten işe yarayıp yaramadığını sayısal olarak gösterir.

İlgili Eğitim

Flutter Eğitimi

Sık Sorulan Sorular

flutter eğitimi sırasında deferred import nasıl öğretilmeli ve hangi sınırları vurgulanmalı?

Öğretirken önce `flutter run --profile --trace-startup` ile baseline startup kaydı alın; sonra deferred import uygulayın ve tekrar ölçün. Vurgu yapılması gereken sınırlar: deferred kütüphanelerin top-level side-effect'lerinin yüklenmeyeceği, Android'de gerçek paketleme için dynamic feature yapılması gerektiği ve loadLibrary çağrısının async olduğu (UI thread'de await edilirse frame drop yaşanabileceği). Somut uygulama ödevi: bir ağır görüntü işleme modülünü deferred yapıp before/after DevTools trace'lerini karşılaştırın.

flutter kursu kapsamında size analysis nasıl yapılır, hangi komutlar kullanılmalı?

Kurs içinde `flutter build apk --release --analyze-size` komutunu gösterin; build tamamlandığında konsolda verilen link ile size analysis UI'ını açın veya `build/flutter_analysis_*.json` dosyasını inceleyin. Ardından hangi paketlerin en büyük yer kapladığını belirleyip gereksiz locale, asset ve dependency kaldırma senaryoları uygulatın. Ayrıca `flutter build apk --split-per-abi` ile ABI bazlı paketlemeyi karşılaştırın.

dart programlama eğitimi alanında TransferableTypedData ne zaman kullanılmalı?

Eğer uygulamanızda büyük binary buffer'lar (ör: multimedya parçaları, resim/vid'o frame'leri) izole'lar arasında paylaşılacaksa TransferableTypedData kullanın. Uygulama: `TransferableTypedData.fromList([bytes])` oluşturup Isolate.spawn'a gönderin, isolate içinde `materialize()` ile erişin. Profiling olarak DevTools Allocation Profile kaydı alın; TransferableTypedData ile heap churn ve GC frekanslarındaki düşüşü önce/sonra olarak karşılaştırın.

AI / LLM Discovery

Bu makale Opendart Akademi Flutter eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt

📚 Bu konuyu Opendart Akademi'de öğrenin: Flutter eğitimi · Flutter eğitimi hakkında · YouTube video dersleri · Abone ol