Uygulamanızı duyarlı tutun

Şekil 1. Kullanıcıya gösterilen ANR iletişim kutusu.

Bu belgede, Android sisteminin bir uygulamanın yanıt verip vermediğini nasıl belirlediği ve uygulamanızın yanıt vermeye devam etmesini nasıl sağlayacağınız açıklanmaktadır.

Kodunuz ne kadar iyi yazılmış olursa olsun, uygulamanızın yavaş çalışması, takılması, uzun süre donması veya girişi işlemek için çok uzun süre beklemesi mümkündür. Uygulamanız ön plandaysa ve yanıt vermiyorsa kullanıcı, Şekil 1'de gösterildiği gibi bir "Uygulama yanıt vermiyor" (ANR) iletişim kutusu görür. ANR iletişim kutusu, kullanıcının uygulamayı kapanmaya zorlamasına olanak tanır. Uygulama ön planda değilse sessizce durdurulur. ANR iletişim kutularını en aza indirmek için uygulamanızın duyarlı olacak şekilde tasarlanması çok önemlidir.

ANR tetikleyicileri

Genellikle sistem, bir uygulama ana iş parçacığında (kullanıcı arayüzü iş parçacığı olarak da bilinir) kullanıcı girişine yanıt veremediğinde ANR kilitlenmesi gösterir. Bu durum, sistemin gelen kullanıcı girişi etkinliklerini işlemesini engeller.

Örneğin, bir uygulama kullanıcı arayüzü iş parçacığında ağ erişimi gibi engelleyici bir G/Ç işlemi gerçekleştirirse ANR oluşabilir. Başka bir örnek olarak, bir uygulamanın karmaşık bir bellek içi yapı oluşturmak veya kullanıcı arayüzü iş parçacığında bir oyundaki sonraki hamleyi hesaplamak için çok fazla zaman harcaması verilebilir.

Android'de uygulama yanıt verme hızı, ActivityManager ve WindowManager sistem hizmetleri tarafından izlenir. Android, aşağıdaki koşullardan birini algıladığında bir uygulama için ANR iletişim kutusunu gösterir:

  • 5 saniye içinde tuşa basma veya ekrana dokunma gibi bir giriş etkinliğine yanıt verilmemesi.
  • Bir BroadcastReceiver, ön plan amaçları için 10-20 saniye içinde yürütülmeyi tamamlamaz. Daha fazla bilgi için Yayın alıcısı zaman aşımı başlıklı makaleyi inceleyin.

ANR'lerden kaçınma

Aşağıda ANR'leri önlemeye yönelik genel ipuçları verilmiştir. Farklı ANR türlerini teşhis etme ve hata ayıklama hakkında daha fazla bilgi için bu bölümdeki diğer sayfalara bakın.

  • Ana iş parçacığını her zaman engellenmemiş durumda tutun ve iş parçacıklarını stratejik olarak kullanın.

    • Uygulamanın ana iş parçacığında engelleme veya uzun süren işlemler yapmayın. Bunun yerine, işi arka plan görev dağıtıcılarına (ör. Dispatchers.IO veya Dispatchers.Default) yük aktarmak için Kotlin eş yordamlarını kullanın. Bu arka plan görevlerini güvenli bir şekilde kullanıma sunmak için viewModelScope gibi mekanizmalar kullanın veya bunları Compose durum değişikliklerine yanıt olarak tetiklemek için LaunchedEffect kullanın.

    • Ana iş parçacığı ile diğer iş parçacıkları arasındaki kilit çekişmesini en aza indirmeye çalışın.

    • Ana ileti dizisinde, kullanıcı arayüzüyle ilgili olmayan tüm işleri (ör. yayınları işleme veya hizmetleri çalıştırma) en aza indirin. Kullanıcı arayüzü iş parçacığında çalışan herhangi bir yöntem veya işlev mümkün olduğunca az iş yapmalıdır. Özellikle etkinlikler, onCreate ve onResume gibi önemli yaşam döngüsü yöntemlerinde kurulum için mümkün olduğunca az işlem yapmalıdır. Asla bir composable işlevin içinde doğrudan G/Ç veya ağır, engelleyici hesaplamalar yapmayın. Bu, oluşturma ve yeniden oluşturma sırasında kullanıcı arayüzü iş parçacığını engeller. Arka plan iş parçacığında iş planlama ve kullanıcı arayüzüyle geri iletişim kurma için kullanılabilen çözümler hakkında daha fazla bilgi edinmek istiyorsanız Arka plan görevlerine genel bakış başlıklı makaleyi inceleyin.

    • İş parçacığı havuzlarını bileşenler arasında paylaşırken dikkatli olun. Potansiyel olarak uzun süreli engelleme işlemlerinde ve yayın alma gibi zamana duyarlı görevlerde aynı iş parçacıklarını kullanmayın.

  • Uygulama başlatma hızını yüksek tutun. Uygulamanın başlangıç kodundaki yavaş veya engelleyici işlemleri en aza indirin. Örneğin, bağımlılık ekleme kurulumu sırasında çalıştırılan yöntemler (Hilt ile olduğu gibi) veya Jetpack App Startup kitaplığı kullanılarak başlatılan bileşenler. Temel Profiller, Başlangıç Profilleri ve R8'i kullanarak uygulama başlatma işlemini daha da optimize edebilirsiniz.

  • BroadcastReceiver kullanıyorsanız Context.registerReceiver kullanarak yayın alıcılarını ana olmayan bir iş parçacığında çalıştırmayı düşünebilirsiniz. Daha fazla bilgi için BroadcastReceiver'da ANR'ler başlıklı makaleyi inceleyin.

    • goAsync kullanıyorsanız ANR zaman aşımı gerçekleşmeden önce PendingResult.finish işlevinin hızlı bir şekilde çağrıldığından emin olun.

BroadcastReceiver'daki ANR'ler

Yayın alıcılar, arka planda küçük ve ayrı miktarlarda iş yapmak üzere tasarlandığından (ör. ayarları kaydetme veya Notification kaydetme) BroadcastReceiver yürütme süresi sınırlıdır. Bu nedenle, kullanıcı arayüzü iş parçacığında çağrılan diğer yöntemlerde olduğu gibi, uygulamalar yayın alıcısında uzun sürebilecek işlemleri veya hesaplamaları yapmaktan kaçınmalıdır. Uzun süren görevleri kullanıcı arayüzü iş parçacığı üzerinden gerçekleştirmek yerine daha sonra yürütülmek üzere arka planda gerçekleştirin. Olası çözümler hakkında daha fazla bilgi için Arka plan görevlerine genel bakış başlıklı makaleyi inceleyin.

BroadcastReceiver nesneleriyle ilgili bir diğer yaygın sorun, bu nesnelerin çok sık yürütülmesidir. Sık arka plan yürütme, diğer uygulamaların kullanabileceği bellek miktarını azaltabilir. BroadcastReceiver nesnelerini verimli bir şekilde etkinleştirme ve devre dışı bırakma hakkında daha fazla bilgi için Yayınlara genel bakış başlıklı makaleyi inceleyin.

Duyarlılığı artırma

Genellikle 100-200 ms, kullanıcıların bir uygulamada yavaşlık algıladığı eşiktir. Uygulamanızın kullanıcılara hızlı yanıt veriyormuş gibi görünmesini sağlamak için ek ipuçlarını aşağıda bulabilirsiniz:

  • Uygulamanız, kullanıcı girişine yanıt olarak arka planda çalışıyorsa kullanıcı arayüzünüzde CircularProgressIndicator veya LinearProgressIndicator gibi bir öğeyle ilerleme kaydedildiğini gösterin.

  • Özellikle oyunlar için, arka plan eş yordamında veya çalışan iş parçacığında hamlelerle ilgili hesaplamalar yapın.

  • Uygulamanızın zaman alan bir ilk kurulum aşaması varsa açılış ekranı göstermeyi veya ilk kompozisyonunuzu mümkün olduğunca hızlı bir şekilde oluşturmayı deneyin. Yükleme işleminin devam ettiğini belirtin ve kullanıcı arayüzü durumunu eşzamansız olarak doldurun. Her iki durumda da, kullanıcının uygulamanın donduğunu düşünmemesi için ilerleme kaydedildiğini bir şekilde belirtmenizi öneririz.

  • Uygulamanızın yanıt verme hızındaki darboğazları belirlemek için Perfetto ve CPU Profiler gibi performans araçlarını kullanın.