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, kullanıcı arayüzünü güncellemekten sorumlu olan uygulamanın ana iş parçacığı kullanıcı giriş etkinliklerini işleyemediği veya çizim yapamadığı için kullanıcıda hayal kırıklığına neden olur. 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 koşullardan biri gerçekleştiğinde uygulamanız için 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ütülüyor: Uygulamanız tarafından beyan edilen bir hizmet birkaç saniye içinde
Service.onCreateveService.onStartCommand/Service.onBindyürütülmesini tamamlayamıyorsa. Service.startForegroundçağrılmadı: Uygulamanız ön planda yeni bir hizmet başlatmak içinContext.startForegroundServicekullanıyorsa ancak hizmet 5 saniye içindestartForegroundçağrısı yapmıyorsa.- Niyet yayını: Bir
BroadcastReceiverbelirli bir süre içinde yürütülmeyi tamamlamadıysa. Uygulama ön planda herhangi bir etkinlik gösteriyorsa bu zaman aşımı 5 saniyedir. JobScheduleretkileşimleri: BirJobServicebirkaç saniye içindeJobService.onStartJobveyaJobService.onStopJob'den dönmezse ya da kullanıcı tarafından başlatılan bir iş başlarsa ve uygulamanızJobService.onStartJobçağrıldıktan sonra birkaç saniye içindeJobService.setNotification'u ç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 ise ANR'ler açıkça belirtilir ve uygulamaya bildirilir.
Uygulamanızda ANR'ler yaşanıyorsa sorunu teşhis etmek ve düzeltmek için bu belgedeki yönergeleri kullanabilirsiniz.
ANR'leri teşhis etme
ANR'leri teşhis ederken dikkat etmeniz gereken bazı yaygın kalıplar vardır:
- Uygulama, ana iş parçacığında G/Ç içeren yavaş işlemler yapıyor.
- Uygulama, ana iş parçacığında uzun bir hesaplama yapıyor.
- Ana iş parçacığı başka bir işleme senkron bir bağlayıcı araması yapıyor ve bu işlemin yanıt vermesi 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 blok beklenirken engellendi.
- 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 ileti dizisi 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 pilin boşalmasını ölçebilirsiniz.
Hata ayıkla
Debug, uygulamalardaki duraklama ve gecikmeleri belirlemek için izleme ve ayırma sayıları da dahil olmak üzere geliştirme sırasında Android uygulamalarını incelemenize yardımcı olur.
Ayrıca, çalışma zamanı ve yerel bellek sayaçlarını almak için Debug simgesini de kullanabilirsiniz. Bu sayaçlar ve bellek metrikleri, belirli bir işlemin bellekte kapladığı yeri belirlemenize yardımcı olabilir.
ApplicationExitInfo
ApplicationExitInfo, Android 11 (API düzeyi 30) veya sonraki sürümlerde kullanılabilir ve uygulamanın çıkış nedenleri hakkında bilgi sağlar. Bu sorunlar arasında ANR'ler, düşük bellek, uygulama çökmeleri, aşırı CPU kullanımı, kullanıcı kesintileri, sistem kesintileri ve çalışma zamanında istenen izin değişiklikleri yer alır.
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'ı uygulama veya etkinlik düzeyinde kullanabilirsiniz.
Arka planda ANR iletişim kutularını etkinleştirme
Android, yayın mesajını işlemek için çok uzun süre bekleyen uygulamalarla ilgili ANR iletişim kutularını yalnızca cihazın Geliştirici seçenekleri bölümünde Tüm ANR'leri göster etkinse gösterir. Bu nedenle, uygulama performans sorunları yaşasa bile arka plan ANR iletişim kutuları her zaman kullanıcıya gösterilmez.
Yeniden oluşturma ile ilgili performans sorunları
Yeniden oluşturma darboğazlarını takip etmek için Android Studio Profiler ve Layout Inspector'ı kullanın. Daha fazla bilgi için Jetpack Compose Performansı konusuna bakın.
İzleme dosyası çekme
Android mağazaları, ANR yaşadığında izleme bilgilerini kaydeder. 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ı bulunur. Android Debug Bridge (adb)'yi kök olarak kullanarak bir cihaz veya emülatörden ANR izlerine erişebilirsiniz:
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 bir 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ından yararlanabilirsiniz.
Ana iş parçacığında yavaş kod
Kodunuzda, uygulamanın ana iş parçacığının 5 saniyeden uzun süre boyunca meşgul olduğu yerleri belirleyin. Uygulamanızdaki şüpheli kullanım alanlarını bulun ve ANR'yi yeniden oluşturmaya çalışın.
Sık karşılaşılan bir sorun, doğrudan bir composable içinde 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şlemleri yürütmek, ana iş parçacığında yavaş işlemlere yol açan yaygın bir nedendir ve bu durum ANR'lere neden olabilir. Geliştiriciler, Compose'da ilk durumu elde etmeye çalışırken genellikle yanlışlıkla disk okuma işlemlerini (ör. SharedPreferences veya veritabanı çağrıları) tetikler.
Uzun süren G/Ç işlemlerini kullanıcı arayüzü katmanından uzakta yürütün. withContext(Dispatchers.IO) kullanın veya daha da iyisi, ViewModel içinde veri katmanında Repository kullanın.
Kilitlenmeler
Bir iş parçacığı, gerekli bir kaynak başka bir iş parçacığı tarafından tutulduğu için bekleme durumuna girdiğinde kilitlenme meydana gelir. Bu iş parçacığı da ilk iş parçacığı tarafından tutulan bir kaynağı beklemektedir. Uygulamanın ana iş parçacığı bu durumdaysa ANR'lerin gerçekleşmesi olasıdır.
Kilitlenmeler, bilgisayar biliminde iyi çalışılmış bir olgudur ve kilitlenmeleri önlemek için kullanabileceğiniz kilitlenme önleme algoritmaları vardır.
Daha fazla bilgi için Wikipedia'daki Kilitlenme ve Kilitlenme önleme algoritmaları başlıklı makaleleri inceleyin.
Kotlin ve Compose kullanırken, UI iş parçacığını dondurmak yerine yürütme bağlamını askıya alarak iş parçacığı engellemeyi önlemek için temel kilitleri engellemeyen coroutine Mutex'leriyle (Mutex.withLock) 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 yayın mesajlarına yanıt verebilir. Örneğin, uçak modunu etkinleştirebilir veya devre dışı bırakabilir ya da bağlantı durumunu değiştirebilir. Bir uygulama yayın mesajını işlemek için çok uzun süre beklediğinde ANR oluşur.
ANR, aşağıdaki durumlarda oluşur:
- Bir yayın alıcısı,
onReceiveyöntemini önemli bir süre içinde yürütmeyi tamamlamadı. - Bir yayın alıcısı
goAsyncişlevini çağırıyor ancakPendingResultnesnesindefinishişlevini çağıramıyor.
Uygulamanız, BroadcastReceiver öğesinin onReceive yönteminde yalnızca kısa işlemler gerçekleştirmelidir. Ancak uygulamanız bir anons sonucunda daha karmaşık bir işlem gerektiriyorsa görevi ViewModel'ya (Kotlin eş yordamları, kapsamları ve görev dağıtıcılarının gücünden yararlanarak) ertelemelisiniz. Görevin en fazla birkaç saniye sürmesi bekleniyorsa herhangi bir tür durum bilgisi depolayıcıya veya birkaç saniyeden uzun sürmesi beklenen görevler için WorkManager'ye ertelemelisiniz.
GameActivity
GameActivity kitaplığı, C veya C++ ile yazılmış oyun ve uygulamaların örnek olaylarında ANR sayısını azaltmıştır. Mevcut yerel etkinliğinizi GameActivity ile değiştirirseniz kullanıcı arayüzü iş parçacığının engellenmesini 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. İş parçacıkları hakkında daha fazla bilgi için İş parçacığı oluşturma ile daha iyi performans başlıklı makaleyi inceleyin.
Ek kaynaklar
İçeriği görüntüleme
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Aşırı sayıda uyandırma