• 29.10.2026 21:13:21
  • İbrahim Gökyar

A practical guide for experienced developers: measurable steps to improve 90th-percentile frame times using selective rebuilds, isolates, and render-layer optimizations during Flutter mobile development. Presented from the perspective of Flutter and Dart training with reproducible measurements.

Flutter selective rebuild ve state management ile performans optimizasyonu

Profiling: Flutter DevTools ile gerçek performans ölçümü

Profil başlamadan önce hedef cihazda baseline almak zorunlu: bir fiziksel cihazta "flutter run --profile" komutu ile uygulamayı çalıştırın, ardından Chrome/IDE'den Flutter DevTools - Performance -> CPU Profiler ve Timeline kayıtlarını alın. Somut adım: terminalde "flutter run --profile --trace-skia" çalıştırıp DevTools'ta Timeline kaydını 30-60 saniye boyunca alın; kayıt sonunda exported timeline JSON dosyasını kaydedin ve p90 frame time için analiz yapın.

Ölçüm için kullanacağınız metrikler ve araçlar: DevTools Timeline (frame, raster ve GPU zamanları), DevTools Memory (heap snapshot) ve Android systrace / ios Instruments. Örneğin Android systrace almak için: "flutter run --profile --trace-startup" veya adb shell perfetto komut zinciri kullanın. Neden: DevTools CPU profili fonksiyon bazlı hot path'i, Timeline ise main vs raster thread ayrımını gösterir; bu mekanizma hangi thread'in darboğaz yarattığını doğrudan açığa çıkarır.

Once/after karşılaştırma mantığı: 1) Baseline alın (p50, p90 frame süreleri, GC sayısı). 2) Bir değişiklik uygulayın (örnek: setState yerine context.select kullanımı). 3) Aynı senaryoda tekrar profile alın. Baseline ve yeni timeline JSON'larını kıyaslamak için basit bir script kullanın; p90 hesaplama örneği son bölümde verildi. Bu süreç, yaptığınız değişikliğin etkisini ölçülebilir şekilde gösterir.

State management: selective rebuild - Provider / Riverpod ile örnek

Flutter state management kritik olduğunda gereksiz rebuild'leri önlemek en yüksek getiriyi verir. Somut örnek: Provider kullanıyorsanız context.watch yerine context.select kullanarak sadece ilgili alt alan değiştiğinde rebuild alın. Kod örneği:

// model.dart
class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void inc() { _count++; notifyListeners(); }
}

// widget.dart
final count = context.select((CounterModel m) => m.count);
return Text('$count');

Neden işe yarıyor: context.select, ChangeNotifier'daki notifyListeners tetiklendiğinde yalnızca seçilen değerin '== operatoru' ile değişip değişmediğini kontrol eder; böylece aynı modelde başka alan değiştiğinde widget rebuild olmaz. Ölçüm: DevTools'ta Widget rebuild stats'ı aktif edip bir senaryoyu 50 iterasyon çalıştırın; rebuild sayısını ve CPU time'ı karşılaştırın.

Isolate ve compute: Dart iş yüklerini UI thread'ten ayırma

Ağdan gelen büyük JSON veya görüntü decode gibi CPU-ağır işler main isolate'ta yapılırsa frame jank üretir. Hızlı çözüm: Flutter'ın compute yordamını veya doğrudan Isolate.spawn ile işi başka bir isolate'a taşıyın. Basit compute örneği:

// heavy_parsing.dart
Map parseHeavy(String jsonStr) => jsonDecode(jsonStr);

// usage.dart
final result = await compute(parseHeavy, jsonString);

Daha büyük veri/ikili transferlerinde TransferableTypedData kullanın; bu, Uint8List kopyasını ortadan kaldırarak bellekte kopyalama maliyetini düşürür. Isolate.spawn ile TransferableTypedData örneği:

// spawn_example.dart
void isolateEntry(SendPort sendPort) async {
  final rp = ReceivePort();
  sendPort.send(rp.sendPort);
  await for (final msg in rp) {
    if (msg is TransferableTypedData) {
      final data = msg.materialize().asUint8List();
      // işlem yap
      sendPort.send('done');
    }
  }
}

// main
final rp = ReceivePort();
final iso = await Isolate.spawn(isolateEntry, rp.sendPort);
final sp = await rp.first as SendPort;
sp.send(TransferableTypedData.fromList([bigUint8List]));

Neden: compute/isolate UI thread'i bloklamaz çünkü Dart VM her isolate için ayrı event loop ve stack kullanır; fakat isolate spawn maliyeti vardır (örneğin küçük görevler için spawn overhead parse süresini artırabilir). Ölçüm: DevTools Memory ile heap churn, Timeline ile main-thread blokaj sürelerini karşılaştırın; ayrıca Stopwatch ile spawn latency ölçün.

Render layer optimizasyonları: RepaintBoundary, const kullanım ve image cache

RepaintBoundary eklemek repaint alanını sınırlar; örnek: sık güncellenen bir list item'ı ayrı repaint boundary içine alın. Kod örneği:

Widget build(BuildContext context) {
  return RepaintBoundary(
    child: ListTile(...),
  );
}

Görüntüleri optimize ederken cacheWidth/cacheHeight parametresini kullanın veya ImageCache limitlerini ayarlayın: uygulama başında PaintingBinding.instance.imageCache.maximumSizeBytes = 50 * 1024 * 1024; ile toplam image cache boyutunu kısıtlayın ve Image.network'te cacheWidth kullanın. Örnek:

// main.dart init
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  PaintingBinding.instance.imageCache.maximumSizeBytes = 50 * 1024 * 1024; // 50MB
  runApp(MyApp());
}

// widget
Image.network(url, width: 300, cacheWidth: 300);

Edge case: Her şeyi const yapmak her zaman iyi değil - const yalnızca compile-time sabitleri ifade eder; runtime veriye bağlı child'lar için const kullanmak anlamsızdır. Ayrıca RepaintBoundary fazla kullanımı compositing maliyetini artırır; hedefiniz repaint hotspot'ları sınırlandırmak olmalı. Ölçüm: DevTools'ta Raster thread zamanını (raster_thread_time) karşılaştırın.

Benchmark otomasyonu: CI entegrasyonu ve geçiş kriterleri

Performans iyileştirmesinin sürdürülebilir olması için CI'ye basit bir perf testi ekleyin. Entegre yaklaşım: firebase test lab ya da kendi lab cihazınız üzerinde "flutter drive --profile --trace-skia --target=test_driver/perf.dart" komutunu çalıştırarak timeline export edin. Komut örneği:

flutter drive --profile --target=test_driver/perf.dart --driver=test_driver/driver.dart
// sonra DevTools export edilen timeline.json'u al

P90 karşılaştırması için küçük bir Dart script'i ile timeline JSON'u okuyup frame sürelerini hesaplayın; basit örnek:

// tools/compare_perf.dart
import 'dart:convert';
import 'dart:io';

void main(List args) {
  final baseline = jsonDecode(File(args[0]).readAsStringSync());
  final current = jsonDecode(File(args[1]).readAsStringSync());
  double p90(Map data) {
    final frames = (data['traceEvents'] as List)
        .where((e) => e['name'] == 'Frame')
        .map((e) => e['dur'] as num)
        .toList()..sort();
    return frames[(frames.length * 90 / 100).floor()] / 1000.0; // ms
  }
  print('baseline p90: ${p90(baseline)} ms');
  print('current p90: ${p90(current)} ms');
}

Geçiş kriterleri örneği: p90'da en az %15 iyileşme veya bellek churn'da %25 azalma. CI içinde başarısız olursa PR bloklayıcı yapın. Bu, cross platform mobil uygulama geliştirme bağlamında dağıtık cihazlarda tutarlı performans sağlamak için gereklidir.

Related Course

Flutter Eğitimi

Frequently Asked Questions

flutter state management ile rebuild'leri nasıl ölçerim ve azaltırım?

Ölçüm: Flutter DevTools'ta Widget rebuild stats ve Timeline kaydı alın; ayrıca kodda debug amaçlı RebuildCounter widget kullanabilirsiniz. Azaltma: Provider context.select veya Riverpod ProviderScope/selector kullanarak sadece gerekli alt ağaçları dinleyin; örnek: context.select((M m) => m.value). Test: değişiklikten önce/sonra DevTools timeline ve rebuild sayısını karşılaştırın.

dart programlama eğitimi sırasında isolate kullanımı ne zaman avantaj sağlar?

Isolate'lar CPU-ağır, uzun süreli işlemlerde (büyük JSON parse, görüntü işleme, sık GC yaratan işler) avantajlıdır. Somut: compute ile JSON parse'ı taşımak ana thread blokajını ortadan kaldırır. Ancak küçük görevlerde spawn overhead maliyetli olabilir; bu yüzden Stopwatch ile spawn+iş sürelerini ölçün ve eğer spawn + işlem > main-thread işlem süresinden az, isolate tercih edin.

flutter mobil uygulama geliştirme için image cache ve memory tuning nasıl yapılır?

Uygulama başlangıcında PaintingBinding.instance.imageCache.maximumSize veya maximumSizeBytes ayarlayın ve Image.network/NetworkImage kullanırken cacheWidth/cacheHeight kullanın. Ağ ve cihaz farklılıkları için cached image boyutunu dinamik ayarlamak iyi bir pratiktir. Ölçüm: DevTools Memory snapshotları ile heap kullanımını ve GC frekansını kontrol ederek ayarın etkisini doğrulayı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

📚 Learn this topic with Opendart: Flutter Training · YouTube video lessons · Subscribe