WebView durumunu verimli bir şekilde yönetme

Bir Android uygulamasının yaşam döngüsünü yönetirken arka planda kaynak geri kazanımı sırasında kullanıcı durumunu korumak, sorunsuz bir kullanıcı deneyiminin temel bileşenidir. Web iş akışlarını içeren uygulamalarda WebView.saveState(Bundle), WebView'ın gezinme geçmişini ve durumunu Bundle olarak serileştirmenize olanak tanır. Bu veriler daha sonra WebView.restoreState(Bundle) kullanılarak geri yüklenebilir.

Ancak standart uygulamalar, yoğun göz atma oturumlarında işlem boyutu sınırlamalarıyla karşılaşabilir. Bu sayfada, bu mimari sınırlamalar açıklanmakta ve gezinme geçmişini korurken bellekle ilgili istisnaları önlemeye yönelik stratejiler sunulmaktadır.

1 MB işlem sınırı ve durum temizleme

Android, savedInstanceState içinde depolanabilecek toplam veri hacmi için 1 MB'lık katı bir sınır uygular. 1 MB'lık bu bütçe, uygulamanın tüm süreci boyunca paylaşılır. Bir uygulama birden fazla WebView örneği içeriyorsa bunların ortak gezinme durumu ve geçmişi, bu tek paylaşılan tahsis içinde yer almalıdır. Bu sınırın aşılması TransactionTooLargeException hatasına neden olur ve uygulama çöker.

Yaygın ancak sorunlu bir azaltma stratejisi, WebView durum paketinin boyutunu izlemeyi ve rastgele bir güvenlik eşiğini (ör. 300 KB) aşarsa WebView geçmişini tamamen temizlemeyi içerir. Bu durum kilitlenmeyi önlese de kullanıcı deneyiminde ciddi gerilemelere yol açar:

  • Geriye doğru gezinme kaybı: Android, diğer görevler için bellek kazanmak amacıyla arka plandaki uygulama işlemlerini genellikle sonlandırır. Gezinme geçmişini korumak için saveState(Bundle) yaşam döngüsü geri çağırma yöntemi içinde onSaveInstanceState() kullanabilirsiniz. 1 MB işlem sınırını aşmamak için bu geçmişi silerseniz tüm gezinme yığını kaybolur. Kullanıcı uygulamaya döndüğünde, işlem yeniden başlatılmış olsun veya olmasın, geriye doğru gezinmeyi destekleyecek geçmiş bağlam kalmadığından sistemin geri düğmesi bileşenden veya uygulamadan hemen çıkar.

  • BFCache geçersiz kılma: Geçmişin temizlenmesi, uygulamanın geri-ileri önbelleği (BFCache) kullanmasını engeller ve daha önce ziyaret edilen sayfaların anında oluşturulması özelliğini kaldırır.

  • Gecikme süresinin artması: Kullanıcılar, WebView'daki mevcut durumlarını kaybeder. Bu nedenle, tam yeniden gezinme ve yeniden başlatma işlemi yapılması gerekir. Bu işlem, ağ yükünü ve işlem gecikmesini önemli ölçüde artırır.

Mimari azaltma stratejileri

TransactionTooLargeException'ın, geçmişin tamamen silinmesi nedeniyle kullanıcı deneyimini düşürmeden kilitlenmesini önlemek için durum tutma ve bellek verimliliği arasında sıkı bir denge kurmanız gerekir. Aşağıdaki optimizasyon stratejilerini uygulayarak temel gezinme geçmişini ve oturum bütünlüğünü korurken 1 MB'lık işlem bütçesini güvenli bir şekilde yönetebilirsiniz.

Durum serileştirme için boyut sınırları zorunlu kılın

Gezinme yığını çok büyüdüğünde tamamen silmek yerine, geçmiş verileri kesmek daha etkili bir yöntemdir:

  • Hedeflenen bırakma politikası: Belirli bir bayt sınırını (örneğin, WebViewCompat.saveState(webView, outState, maxSizeBytes)) zorunlu kılarken durumu serileştirmek için WebViewCompat.saveState() kullanın. Bu API, toplam yük tanımladığınız ayırmaya sığana kadar eski gezinme girişlerini otomatik olarak sırayla bırakır. Önemli olarak, bu yalnızca etkin WebView'nin canlı geçmişini değiştirmeden veya temizlemeden seri hale getirilmiş Bundle'yı kısaltır. Böylece, geriye doğru anında gezinme tamamen bozulmadan kalır.

  • İleri girişleri kaldırma: Uygulama arayüzünde geri düğmesi varsa ancak özel bir ileri gezinme düğmesi yoksa saveState API'sinin includeForwardState parametresini false olarak ayarlayarak tüm ileri gezinme girişlerini silebilirsiniz. Bu, kullanıcının mevcut gezinme yollarını etkilemeden yük boyutunu önemli ölçüde azaltır.

HTTP Cache Quota API ile kaynak gecikmesini yönetme

saveState, geçici gezinme geçmişi için 1 MB'lık Bundle sınırı yönetirken HTTP Cache Quota API, profiller bazında kalıcı web kaynakları (disk önbelleği) üzerinde manuel kontrol sağlar. Bu, kısa süreli gezinme bağlamı ile uzun süreli önbelleğe alınmış öğeler arasında net bir ayrım oluşturur.

Uygun bir kota seçmek performans açısından ödün vermeyi gerektirir:

  • Daha yüksek kotalar, daha fazla öğeyi diskte tutarak çevrimdışı kullanılabilirliği ve kaynak yükleme gecikmesini iyileştirir.
  • Daha düşük kotalar, uygulamanın diskteki yerini en aza indirir ve işletim sistemi tarafından yönetilen önbelleğin diğer önemli uygulama verilerinden temizlenmesini önler.

Bu ayarlar, uygulama yeniden başlatıldığında korunur ve ana iş parçacığından yapılandırılmalıdır.

Aşağıdaki uygulamada, varsayılan profil için disk önbelleği kotasının nasıl yapılandırılacağı gösterilmektedir:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
    WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
    val defaultProfile = ProfileStore.getInstance()
        .getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME)
    val httpCache = defaultProfile.httpCache

    // Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
    httpCache.setQuotaBytes(50L * 1024 * 1024)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
    WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
    Profile defaultProfile = ProfileStore.getInstance()
        .getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME);
    HttpCache httpCache = defaultProfile.getHttpCache();

    // Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
    httpCache.setQuotaBytes(50L * 1024 * 1024);
}

Kota boyutlandırma stratejileri, yaşam döngüsü yönetimi ve profil sınırları hakkında daha fazla bilgi için WebView'da HTTP önbellek kotasını yönetme başlıklı makaleyi inceleyin.

Performansla ilgili önemli noktalar

Aşağıdaki noktalarda, WebView durum davranışını yöneten teknik sınırlamalar ve dahili veri davranışları vurgulanmaktadır:

  • Opak PageState blob'lar: saveState tarafından depolanan verilerin yaklaşık% 70'i, oluşturma motorundan gelen dahili PageState blob'lardan oluşur. Bu veriler, form girişleri ve iFrame kaydırma konumları dahil olmak üzere ayrıntılı oturum durumlarını yakalar. Bu blob'lardaki segmentleri manuel olarak ayrıştırmaya veya kaldırmaya çalışmayın. Bu işlem ciddi güvenlik riskleri oluşturur ve oturum geri yükleme bütünlüğünü bozar.

  • Ayrıntılı geçmiş yönetimi: Standart WebBackForwardList API, geçmiş öğelerinin tek tek rastgele kaldırılmasını doğal olarak desteklemez. Katı durum yönetimi için mimari güvenliği sağlamak amacıyla WebViewCompat.saveState() içinde maxSizeBytes ve includeForwardState parametrelerini kullanarak kesme stratejileri uygulamanız gerekir.