Ce document décrit comment le système Android détermine si une application ne répond pas et montre comment maintenir la réactivité de votre application.
Même si votre code est bien écrit, il est possible que votre application soit lente, qu'elle se bloque, qu'elle se fige pendant de longues périodes ou qu'elle prenne trop de temps à traiter les données. Si votre application est exécutée au premier plan et ne répond pas, l'utilisateur voit apparaître une boîte de dialogue ANR (L'application ne répond pas), comme le montre l'image 1. La boîte de dialogue ANR permet à l'utilisateur de forcer la fermeture de l'application. Si l'application n'est pas au premier plan, elle est arrêtée silencieusement. Il est essentiel de concevoir la réactivité dans votre application pour minimiser les boîtes de dialogue ANR.
Déclencheurs d'ANR
En règle générale, le système affiche une erreur ANR si une application ne peut pas répondre à l'entrée utilisateur sur le thread principal (également appelé thread UI), ce qui l'empêche de traiter les événements entrants d'entrée utilisateur.
Par exemple, une erreur ANR peut se produire si une application effectue une opération d'E/S bloquante, telle qu'un accès réseau, sur le thread UI. Autre exemple : Une application passe trop de temps à créer une structure élaborée en mémoire ou à calculer le prochain coup dans un jeu sur le thread UI.
Dans Android, la réactivité de l'application est surveillée par les services système ActivityManager
et WindowManager
. Android affiche la boîte de dialogue ANR d'une application lorsqu'il détecte l'une des situations suivantes :
- Aucune réponse à un événement d'entrée (tel qu'un appui sur une touche ou un appui sur l'écran) dans les 5 secondes.
- L'exécution d'un
BroadcastReceiver
ne se termine pas dans un délai de 10 à 20 secondes pour les intents de premier plan. Pour en savoir plus, consultez la section Délai avant expiration du broadcast receiver.
Éviter les erreurs ANR
Vous trouverez ci-dessous des conseils généraux pour éviter les erreurs ANR. Pour en savoir plus sur le diagnostic et le débogage des différents types d'erreurs ANR, consultez les autres pages de cette section.
Laissez le thread principal débloqué en permanence et utilisez les threads de manière stratégique.
N'effectuez pas d'opérations bloquantes ou de longue durée sur le thread principal de l'application. À la place, créez un thread de travail et effectuez la majeure partie des tâches à cet endroit.
Essayez de minimiser les conflits de verrouillage entre le thread principal et les autres threads.
Réduisez les tâches non liées à l'UI sur le thread principal, par exemple lors de la gestion des broadcasts ou de l'exécution de services. Toute méthode exécutée dans le thread UI doit effectuer le moins de tâches possible sur ce thread. En particulier, les activités doivent faire le moins de configuration possible dans les méthodes de cycle de vie clés, telles que
onCreate()
etonResume()
. Consultez la section Présentation des tâches en arrière-plan pour en savoir plus sur les solutions disponibles pour planifier des tâches sur un thread d'arrière-plan et communiquer avec l'interface utilisateur.Soyez prudent lorsque vous partagez des pools de threads entre des composants. N'utilisez pas les mêmes threads pour des opérations potentiellement bloquantes et des tâches urgentes, telles que la réception de diffusions.
Accélérez le démarrage de l'application. Réduisez les opérations lentes ou bloquantes dans le code de démarrage de l'application, telles que les méthodes exécutées lors de l'initialisation de Dagger.
Si vous utilisez
BroadcastReceiver
, envisagez d'exécuter des broadcast receivers dans un thread non principal à l'aide deContext.registerReceiver
. Pour en savoir plus, consultez la section ANR dans BroadcastReceiver.- Si vous utilisez
goAsync()
, assurez-vous quePendingResult.finish
est appelé rapidement avant le délai avant expiration de l'ANR.
- Si vous utilisez
ANR dans BroadcastReceiver
Le temps d'exécution de BroadcastReceiver
est limité, car les broadcast receivers sont censés effectuer de petites tâches discrètes en arrière-plan, telles que l'enregistrement d'un paramètre ou l'enregistrement de Notification
. Ainsi, comme pour les autres méthodes appelées dans le thread UI, les applications doivent éviter les opérations ou les calculs potentiellement longs dans un broadcast receiver. Au lieu d'effectuer des tâches de longue durée via le thread UI, effectuez-les en arrière-plan pour une exécution ultérieure. Pour en savoir plus sur les solutions possibles, consultez la section Présentation des tâches en arrière-plan.
Un autre problème courant avec les objets BroadcastReceiver
survient lorsqu'ils s'exécutent trop fréquemment. L'exécution fréquente en arrière-plan peut réduire la quantité de mémoire disponible pour d'autres applications. Pour en savoir plus sur l'activation et la désactivation efficaces des objets BroadcastReceiver
, consultez la section Présentation des diffusions.
Renforcez la réactivité
En règle générale, la plage de 100 à 200 ms correspond au seuil au-delà duquel les utilisateurs perçoivent une lenteur dans une application. Voici quelques conseils supplémentaires pour que votre application paraisse réactive aux utilisateurs :
Si votre application fonctionne en arrière-plan en réponse à une entrée utilisateur, montrez que la progression est en cours, par exemple avec un
ProgressBar
dans votre interface utilisateur.Pour les jeux en particulier, effectuez des calculs de mouvements dans un thread de travail.
Si la phase de configuration initiale de votre application prend beaucoup de temps, envisagez d'afficher un écran de démarrage ou la vue principale le plus rapidement possible. Indiquez que le chargement est en cours et remplissez les informations de manière asynchrone. Dans les deux cas, nous vous recommandons d'indiquer d'une manière ou d'une autre cette progression, afin que l'utilisateur ne perçoive pas que l'application est figée.
Identifiez les goulots d'étranglement qui affectent la réactivité de votre application à l'aide d'outils de performances tels que Perfetto et le Profileur de processeur.