• 23.08.2026 09:18:32
  • Admin Admin

Flutter mobil uygulama geliştirme projelerinde WebView, harita ve kamera gibi PlatformView bileşenlerinin hibrit bileşim maliyetini ölçmeyi, doğru render modunu seçmeyi ve kaydırma jank’ini azaltmayı öğrenin.

Flutter Mobil Uygulama Geliştirmede Platform View Performans Rehberi

Flutter mobil uygulama geliştirmede PlatformView darboğazını tanımlama

PlatformView, Flutter sahnesine Android View veya iOS UIView eklediği için normal Flutter widget ağacından farklı bir render hattı kullanır. `webview_flutter`, `google_maps_flutter`, `camera` veya şirket içi native SDK sarmalayıcılarında ilk iş, sorunun Dart tarafındaki build maliyeti mi yoksa platform katmanındaki compositing maliyeti mi olduğunu ayırmaktır. Profil modunda uygulamayı `flutter run --profile --trace-skia` ile başlatın; debug modundaki assertions, JIT derleme ve service extension maliyetleri bu ölçüm için güvenilir değildir.

flutter run --profile --trace-skia
flutter devtools
# DevTools > Performance > Record
# Harita/WebView görünürken 10 saniyelik kontrollü scroll senaryosu kaydedin.

DevTools Performance görünümünde raster thread üzerinde uzun kareler ve `PlatformViewLayer` çevresinde yükselen GPU süresi arayın. Android’de buna ek olarak `adb shell dumpsys gfxinfo com.example.app framestats` çalıştırın; `Draw`, `Prepare` ve `Process` sütunları sürekli yükseliyorsa sorun yalnızca Flutter widget yeniden kurulumu değildir. Aynı navigasyon ve kaydırma senaryosunu PlatformView kapalı bir feature flag ile tekrar kaydedin; iki trace arasındaki p95 frame time farkı, yatırım yapılacak alanı somutlaştırır.

adb shell dumpsys gfxinfo com.example.app reset
# Uygulamada aynı listeyi 3 kez aşağı-yukarı kaydırın.
adb shell dumpsys gfxinfo com.example.app framestats > /tmp/frames.txt

Cross platform mobil uygulama geliştirme için doğru bileşim modunu seçmek

Android PlatformView entegrasyonunda temel tercih, native görünümün Flutter içeriğiyle nasıl birleştirileceğidir. `webview_flutter_android` tarafında bazı durumlarda texture tabanlı yaklaşım daha düşük Flutter UI etkileşim maliyeti üretebilir; ancak native view dönüşümleri, erişilebilirlik düğümleri, klavye, video yüzeyi ve overlay ihtiyaçları hibrit bileşimi gerekli kılabilir. Bu nedenle modu 'hızlı' olduğu varsayımıyla değil, ürün davranışıyla seçin: WebView üzerinde Flutter `TextField`, modal, drag target veya platform görünümünün üstünde animasyonlu katman varsa hibrit bileşimin davranışını gerçek cihazlarda doğrulayın.

Android WebView için `webview_flutter_android` API’siyle controller oluştururken platforma özgü parametreleri açıkça verin. Aşağıdaki yapı, Android tarafındaki controller’a erişimi korur; ayrıca production kodunda user-agent veya JavaScript kanalını yalnızca ihtiyaç varsa açmak, mesaj trafiğini ve saldırı yüzeyini sınırlar.

final PlatformWebViewControllerCreationParams params =
    const PlatformWebViewControllerCreationParams();

final WebViewController controller = WebViewController.fromPlatformCreationParams(
  params,
  onPermissionRequest: (request) {
    request.deny(); // Kamera/mikrofon için uygulama politikasıyla karar verin.
  },
)
  ..setJavaScriptMode(JavaScriptMode.disabled)
  ..setNavigationDelegate(
    NavigationDelegate(
      onNavigationRequest: (request) {
        final uri = Uri.parse(request.url);
        return uri.host == 'docs.example.com'
            ? NavigationDecision.navigate
            : NavigationDecision.prevent;
      },
    ),
  );

iOS’ta `WKWebView` genellikle Flutter metal sahnesiyle farklı bir compositing davranışı gösterir; Android’de iyi görünen bir çözümü iOS’a taşıdığınızı varsaymayın. Xcode Instruments içindeki Core Animation aracında aynı ekranı kaydedin ve `Color Blended Layers` ile yarı saydam Flutter overlay’lerini inceleyin. Platform görünümünün üzerinde `Opacity(opacity: 0.5)` ile tam ekran katman çizmek, alttaki içeriğin yeniden harmanlanmasına neden olur; mümkünse opak bir panel, küçük bir `ClipRect` alanı veya native tarafın kendi overlay API’si kullanın.

Flutter state management ile PlatformView yeniden oluşturmayı engellemek

PlatformView maliyetinin sık görülen nedeni controller değil, widget kimliğinin değişmesidir. `flutter state management` katmanında WebView URL’si, seçili sekme ve ekranın diğer durumu tek bir geniş state nesnesinde tutulup tüm sayfa `watch` edildiğinde, ilgisiz bir sayaç değişikliği dahi `WebViewWidget` ağacını etkileyebilir. Riverpod kullanıyorsanız platform görünümünü yalnızca URL değiştiğinde seçen bir provider ile ayırın; controller’ı `build` içinde üretmek yerine yaşam döngüsü sahibi bir provider veya `State` alanında saklayın.

final selectedUrlProvider = Provider<String>((ref) {
  return ref.watch(articleProvider.select((article) => article.url));
});

class ArticleWebView extends ConsumerStatefulWidget {
  const ArticleWebView({super.key});

  @override
  ConsumerState<ArticleWebView> createState() => _ArticleWebViewState();
}

class _ArticleWebViewState extends ConsumerState<ArticleWebView> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController();
  }

  @override
  Widget build(BuildContext context) {
    final url = ref.watch(selectedUrlProvider);
    return WebViewWidget(key: ValueKey(url), controller: _controller);
  }
}

Bu örnekte `ValueKey(url)` kasıtlı bir sınırdır: URL değişirse yeni native sayfa istenebilir, fakat tema, beğeni sayısı veya üst bar animasyonu değiştiğinde key değişmez. Buna karşılık controller üzerinde URL yüklemek istiyorsanız key’i sabit tutup `ref.listen` ile yalnızca gerçek URL geçişinde `loadRequest` çağırın. Yaygın hata, `UniqueKey()` kullanmaktır; her build’de yeni key üretildiği için framework eski PlatformView’ı dispose edip yenisini oluşturabilir ve WebView scroll konumu ile cookie yükleme süresi kaybolur.

ref.listen<String>(selectedUrlProvider, (previous, next) {
  if (previous != next) {
    _controller.loadRequest(Uri.parse(next));
  }
});

Ölçülebilir optimizasyon: trace karşılaştırması ve liste içi PlatformView sınırı

Bir PlatformView’ı `ListView.builder` içindeki her karta koymak yerine tek bir ayrıntı ekranına taşıyın veya native içeriğin statik önizlemesini Flutter tarafında üretin. Örneğin liste satırında WebView yerine HTML başlığını parse eden `flutter_html` ya da güvenilir bir backend özeti kullanın; kullanıcı ayrıntıya geçtiğinde WebView açın. Bunun nedeni, her görünür satırın native view hiyerarşisi, input bağlantısı ve compositor katmanı oluşturabilmesidir; `AutomaticKeepAliveClientMixin` ile satırları yaşatmak ise geçiş maliyetini azaltırken native bellek tüketimini büyütebilir.

ListView.builder(
  itemCount: articles.length,
  itemBuilder: (context, index) {
    final article = articles[index];
    return ListTile(
      title: Text(article.title),
      subtitle: Text(article.summary, maxLines: 2),
      onTap: () => Navigator.of(context).push(
        MaterialPageRoute(builder: (_) => ArticleWebViewPage(url: article.url)),
      ),
    );
  },
);

Önce-sonra karşılaştırmasını sayısallaştırın: aynı orta seviye fiziksel Android cihazda, uygulamayı profile modunda soğuk başlatın, aynı 30 saniyelik scroll kaydını alın ve DevTools trace’inden UI/raster p50, p95 ve 16.67 ms üzerindeki kare sayısını not edin. Ardından liste içi PlatformView değişikliğini uygulayıp aynı senaryoyu en az beş kez tekrarlayın; ilk kaydı shader ve WebView başlatma etkisi nedeniyle ayrı değerlendirin. Android tarafında `gfxinfo` histogramı ile DevTools bulgusu çelişirse cihazın 90/120 Hz yenileme hızını kontrol edin; 120 Hz ekranda 16.67 ms hedefi değil yaklaşık 8.33 ms kare aralığı kritik hale gelir.

Bu disiplin, bir flutter eğitimi veya flutter kursu içeriğinde genellikle atlanan bir ayrıntıdır: widget rebuild sayısı düşük olsa bile platform compositor gecikebilir. Dart programlama eğitimi sırasında öğrenilen `const`, `select` ve referans eşitliği teknikleri burada yine değerlidir, fakat native görünümün yaşam döngüsü ile frame trace birlikte incelenmeden kök neden bulunmaz.

PlatformView yaşam döngüsü, input ve güvenlikte kenar durumları

WebView veya harita ekranından geri dönüldüğünde controller’a asenkron callback ile komut göndermeden önce widget’ın hâlâ bağlı olduğunu kontrol edin. Özellikle JavaScript channel, konum stream’i veya native SDK callback’i `dispose` sonrasında çalışabilir. `mounted` kontrolü Flutter `State` için gereklidir; ayrıca `StreamSubscription.cancel()` ve controller’ın paket dokümantasyonundaki dispose çağrısı, native kaynakların ekran kapandıktan sonra tutulmasını önler.

late final StreamSubscription<Uri> _links;

@override
void initState() {
  super.initState();
  _links = linkStream.listen((uri) async {
    if (!mounted) return;
    await _controller.loadRequest(uri);
  });
}

@override
void dispose() {
  _links.cancel();
  super.dispose();
}

PlatformView üzerine Flutter `GestureDetector` koymak her zaman beklenen sonucu vermez; hit-test sonucu ve gesture arena kararı native view’a iletilecek dokunmayı değiştirebilir. Harita üzerinde sürüklenebilir bir alt panel gerekiyorsa panelin alanını `Align` ve opak bir `Material` ile sınırlayın, harita alanını kaplayan görünmez bir gesture katmanı kullanmayın. Android’de ayrıca WebView’ın klavye açıldığında yeniden boyutlanması için activity `windowSoftInputMode` davranışını ve Flutter tarafındaki `SafeArea`/`viewInsets` kullanımını gerçek klavye ile test edin; emulator klavyesi bu yolu her zaman temsil etmez.

İlgili Eğitim

Flutter Eğitimi

Sık Sorulan Sorular

Flutter mobil uygulama geliştirmede WebView neden ListView içinde takılıyor?

Her görünür WebView ayrı native view ve compositor katmanı oluşturabilir. Önce `flutter run --profile --trace-skia` ile kaydırma trace’i alın, ardından liste satırındaki WebView’ı Flutter tabanlı özet kartıyla değiştirip p95 raster süresi ile 16.67 ms üzerindeki kare sayısını karşılaştırın. WebView’ı ayrıntı ekranına taşımak çoğu durumda daha öngörülebilir bir yaşam döngüsü verir.

Flutter state management PlatformView yeniden oluşturmayı nasıl önler?

Riverpod, Bloc veya benzeri yapıda PlatformView’ın bağımlılığını daraltın. Riverpod’da `ref.watch(provider.select(...))` ile yalnızca URL gibi gerekli alanı dinleyin; `WebViewController`ı `build` içinde kurmayın ve `UniqueKey()` kullanmayın. URL değişimi için `ref.listen` ile `controller.loadRequest()` çağırmak, ilgisiz state değişikliklerinde native görünümün yok edilmesini engeller.

Cross platform mobil uygulama geliştirme projesinde PlatformView performansı nasıl ölçülür?

Android’de DevTools Performance trace’ini `adb shell dumpsys gfxinfo framestats` ile birlikte kullanın; iOS’ta Xcode Instruments Core Animation kaydı alın. Aynı cihaz, aynı veri ve aynı kullanıcı akışıyla feature flag açık/kapalı ölçüm yapın. İlk çalıştırmayı ayrı tutun; WebView başlatma ve shader hazırlığı ilk trace’i çarpıtabilir.

Flutter eğitimi veya flutter kursu kapsamında PlatformView için hangi pratik yapılmalı?

Bir ekranı önce liste içinde üç WebView ile kurun, profile trace ve `gfxinfo` çıktısını kaydedin; sonra WebView’ları ayrıntı ekranına taşıyın ve aynı kaydırma senaryosunu beş kez tekrar edin. Dart programlama eğitimi açısından ek görev olarak Riverpod `select` kullanıp yalnızca URL değiştiğinde `loadRequest` tetikleyen bir test yazı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