Bir Android uygulamasının kullanıcı arayüzü iş parçacığı çok uzun süre engellendiğinde "Uygulama Yanıt Vermiyor" (ANR) hatası tetiklenir. Uygulama ön plandaysa sistem, Şekil 1'de gösterildiği gibi kullanıcıya bir iletişim kutusu gösterir. ANR iletişim kutusu, kullanıcıya uygulamayı kapanmaya zorlama fırsatı verir.
ANR'ler, uygulamanın kullanıcı arayüzünü güncellemekten sorumlu ana iş parçacığının kullanıcı girişi etkinliklerini işleyememesi veya çizememesi nedeniyle kullanıcıda hayal kırıklığına yol açan bir sorundur. Uygulamanın ana iş parçacığı hakkında daha fazla bilgi için İşlemlere ve iş parçacıklarına genel bakış başlıklı makaleyi inceleyin.
Aşağıdaki durumlardan biri gerçekleştiğinde uygulamanız için bir ANR tetiklenir:
- Giriş gönderme zaman aşımına uğradı: Uygulamanız 5 saniye içinde bir giriş etkinliğine (ör. tuşa basma veya ekrana dokunma) yanıt vermediyse.
- Hizmet yürütme: Uygulamanız tarafından beyan edilen bir hizmet,
Service.onCreateveService.onStartCommand/Service.onBindyürütme işlemini birkaç saniye içinde tamamlayamazsa. Service.startForegroundçağrılmadı: Uygulamanız ön planda yeni bir hizmet başlatmak içinContext.startForegroundServicekullanıyor ancak hizmet 5 saniye içindestartForegroundçağrısı yapmıyor.- Intent yayını: Bir
BroadcastReceiverbelirli bir süre içinde yürütmeyi tamamlamadıysa. Uygulamanın ön planda herhangi bir etkinliği varsa bu zaman aşımı 5 saniyedir. JobScheduleretkileşimleri:JobService, birkaç saniye içindeJobService.onStartJobveyaJobService.onStopJobyönteminden dönmezse ya da kullanıcı tarafından başlatılan bir iş başlar ve uygulamanız,JobService.onStartJobçağrıldıktan sonra birkaç saniye içindeJobService.setNotificationyöntemini çağırmazsa. Android 13 ve önceki sürümleri hedefleyen uygulamalarda ANR'ler sessizdir ve uygulamaya bildirilmez. Android 14 ve sonraki sürümleri hedefleyen uygulamalarda ANR'ler açıktır ve uygulamaya bildirilir.
Uygulamanızda ANR'ler yaşanıyorsa sorunu teşhis edip düzeltmek için bu dokümandaki yönergeleri kullanabilirsiniz.
ANR'leri teşhis etme
ANR'leri teşhis ederken dikkat edilmesi gereken bazı yaygın kalıplar vardır:
- Uygulama, ana iş parçacığında G/Ç içeren yavaş işlemler gerçekleştiriyor.
- Uygulama, ana iş parçacığında uzun bir hesaplama yapıyor.
- Ana iş parçacığı başka bir işleme eşzamanlı bir bağlayıcı çağrısı yapıyor ve bu diğer işlemin geri dönmesi uzun sürüyor.
- Ana iş parçacığı, başka bir iş parçacığında gerçekleşen uzun bir işlem için senkronize edilmiş bir bloğu beklerken engelleniyor.
- Ana iş parçacığı, işleminizde veya bir bağlayıcı çağrısı aracılığıyla başka bir iş parçacığıyla kilitlenmiş durumda. Ana iş parçacığı yalnızca uzun bir işlemin tamamlanmasını beklemiyor, aynı zamanda kilitlenme durumunda.
Aşağıdaki teknikler, ANR'lerinizin nedenini belirlemenize yardımcı olabilir.
HealthStats
HealthStats; toplam kullanıcı ve sistem süresi, CPU süresi, ağ, radyo istatistikleri, ekran açık/kapalı süresi ve uyandırma alarmlarını yakalayarak bir uygulamanın durumuyla ilgili metrikler sağlar. Bu sayede genel CPU kullanımını ve pil tüketimini ölçebilirsiniz.
Hata ayıkla
Debug, geliştirme sırasında Android uygulamalarını incelemenize yardımcı olur. Uygulamalardaki takılma ve gecikmeleri belirlemek için izleme ve ayırma sayıları da buna dahildir.
Çalışma zamanı ve yerel bellek sayaçlarının yanı sıra belirli bir işlemin bellekte kapladığı yeri belirlemenize yardımcı olabilecek bellek metriklerini almak için Debug aracını da kullanabilirsiniz.
ApplicationExitInfo
ApplicationExitInfo, Android 11 (API düzeyi 30) veya sonraki sürümlerde kullanılabilir ve uygulamadan çıkış nedeni hakkında bilgi sağlar. ANR'ler, yetersiz bellek, uygulama kilitlenmeleri, aşırı CPU kullanımı, kullanıcı kesintileri, sistem kesintileri ve çalışma zamanında istenen izin değişiklikleri buna dahildir.
Yüksek düzey modu
StrictMode, uygulamanızı geliştirirken ana iş parçacığında yanlışlıkla yapılan G/Ç işlemlerini bulmanıza yardımcı olur. StrictMode aracını uygulama veya etkinlik düzeyinde kullanabilirsiniz.
Arka planda ANR iletişim kutularını etkinleştir
Android, yayın mesajını işlemek için çok uzun süre harcayan uygulamalar için ANR iletişim kutularını yalnızca cihazın Geliştirici seçenekleri bölümünde Tüm ANR'leri göster seçeneği etkinleştirilmişse gösterir. Bu nedenle, uygulama performans sorunları yaşasa bile arka plan ANR iletişim kutuları kullanıcıya her zaman gösterilmez.
Yeniden oluşturma darboğazları
Yeniden oluşturma darboğazlarını tespit etmek için Android Studio Profiler ve Layout Inspector'ı kullanın. Daha fazla bilgi için Jetpack Compose Performansı başlıklı makaleyi inceleyin.
İzleme dosyası alma
Android, ANR ile karşılaştığında izleme bilgilerini depolar. Eski işletim sistemi sürümlerinde cihazda tek bir /data/anr/traces.txt dosyası bulunur. Daha yeni işletim sistemi sürümlerinde birden fazla /data/anr/anr_* dosyası vardır. ANR izlerine bir cihazdan veya emülatörden erişmek için Android Debug Bridge (adb) aracını root olarak kullanabilirsiniz:
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
Cihazdaki "Hata raporu al" geliştirici seçeneğini veya geliştirme makinenizdeki adb bugreport komutunu kullanarak fiziksel cihazdan hata raporu alabilirsiniz. Daha fazla bilgi için Hata raporlarını yakalama ve okuma başlıklı makaleyi inceleyin.
Sorunları düzeltme
Sorunu belirledikten sonra, sık karşılaşılan sorunları düzeltmek için bu bölümdeki ipuçlarını kullanabilirsiniz.
Ana iş parçacığında yavaş kod
Kodunuzda, uygulamanın ana iş parçacığının 5 saniyeden uzun süre meşgul olduğu yerleri belirleyin. Uygulamanızda şüpheli kullanım alanlarını arayın ve ANR'yi yeniden oluşturmaya çalışın.
Sık karşılaşılan sorunlardan biri, doğrudan bir composable'da uzun süren bir görevdir:
@Composable
fun BadList(rawStrings: List<String>) {
// Math or sorting inside the composable runs on EVERY recomposition pass!
val heavilyProcessedList = rawStrings
.filter { it.isNotBlank() }
.map { it.uppercase().reversed() }
.map { it.computationallyHeavyFunction() }
.sortedBy { it.length }
LazyColumn { items(sortedList) { Text(it) } }
}
// Modern Compose-first fix
@Composable
fun GoodList(viewModel: MyViewModel = viewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
// UI simply renders state; no heavy processing allowed here
LazyColumn { items(uiState.sortedData) { Text(it) } }
}
Ana iş parçacığında G/Ç
Ana iş parçacığında G/Ç işlemlerinin yürütülmesi, ana iş parçacığındaki işlemlerin yavaşlamasının yaygın bir nedenidir ve ANR'lere yol açabilir. Oluşturma'da geliştiriciler, ilk durumu türetmeye çalışırken genellikle yanlışlıkla disk okuma işlemlerini (SharedPreferences veya veritabanı çağrıları gibi) tetikler.
Uzun süren G/Ç işlemlerini kullanıcı arayüzü katmanından uzakta yürütün. withContext(Dispatchers.IO) öğesini bir ViewModel içinde kullanın veya daha da iyisi, veri katmanında bir Repository kullanın.
Kilitlenmeler
Kilitlenme, bir iş parçacığının bekleme durumuna girmesiyle oluşur. Bunun nedeni, gerekli bir kaynağın başka bir iş parçacığı tarafından tutulmasıdır. Bu iş parçacığı da ilk iş parçacığı tarafından tutulan bir kaynağı beklemektedir. Uygulamanın ana iş parçacığı bu durumdaysa ANR'ler meydana gelebilir.
Kilitlenmeler, bilgisayar biliminde iyi incelenmiş bir olgudur ve kilitlenmeleri önlemek için kullanabileceğiniz kilitlenme önleme algoritmaları vardır.
Daha fazla bilgi için Wikipedia'da Kilitlenme ve Kilitlenmeyi önleme algoritmaları başlıklı makaleleri inceleyin.
Kotlin ve Compose'u kullanırken, kullanıcı arayüzü iş parçacığını dondurmak yerine yürütme bağlamını askıya alarak iş parçacığının engellenmesini önlemek için ilkel kilitleri engelleyici olmayan eş yordam Mutex'leri (Mutex.withLock) ile değiştirebilirsiniz. Örneğin:
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
// Modern non-blocking concurrency state architecture
class SecureDataRepository {
private val mutex = Mutex()
suspend fun safeUIAccess() {
// If locked, the main thread suspends seamlessly, preventing an ANR
mutex.withLock {
performSafeOperation()
}
}
}
Yavaş yayın alıcıları
Uygulamalar, yayın alıcıları aracılığıyla uçak modunu etkinleştirme veya devre dışı bırakma ya da bağlantı durumundaki bir değişiklik gibi yayın mesajlarına yanıt verebilir. Uygulamanın, yayın mesajını işlemesi çok uzun sürdüğünde ANR meydana gelir.
ANR aşağıdaki durumlarda gerçekleşir:
- Bir yayın alıcısı, makul bir süre içinde
onReceiveyöntemini yürütmeyi tamamlamadı. - Yayın alıcısı
goAsyncyöntemini çağırıyor ancakPendingResultnesnesindefinishyöntemini çağıramıyor.
Uygulamanız, bir BroadcastReceiver'nin onReceive yönteminde yalnızca kısa işlemler gerçekleştirmelidir. Ancak uygulamanız, yayın mesajı sonucunda daha karmaşık bir işlem gerektiriyorsa görevi ViewModel (Kotlin eş yordamlarının, kapsamlarının ve dağıtıcılarının gücünden yararlanarak) en fazla birkaç saniye sürmesi beklenen görevler için herhangi bir durum bilgisi depolayıcıya veya birkaç saniyeden uzun sürmesi beklenen görevler için WorkManager'e ertelemeniz gerekir.
GameActivity
GameActivity kitaplığı, C veya C++ dilinde yazılmış oyun ve uygulamaların örnek olay incelemelerinde ANR'leri azaltmıştır. Mevcut yerel etkinliğinizi GameActivity ile değiştirirseniz kullanıcı arayüzü iş parçacığı engellemesini azaltabilir ve bazı ANR'lerin oluşmasını önleyebilirsiniz.
ANR'ler hakkında daha fazla bilgi için Uygulamanızın yanıt vermesini sağlama başlıklı makaleyi inceleyin. Mesaj dizileri hakkında daha fazla bilgi için Mesaj dizileriyle daha iyi performans başlıklı makaleyi inceleyin.
Ek kaynaklar
İçerik görüntüleme
Sizin için önerilenler
- Not: JavaScript devre dışı bırakıldığında bağlantı metni gösterilir.
- Aşırı sayıda uyandırma