L'application fait peut-être trop de travail sur son thread principal


379

Je suis nouveau dans l'environnement SDK / API Android. C'est le premier que j'essaie de dessiner un graphique / graphique. J'ai essayé d'exécuter différents types d'exemples de codes sur l'émulateur en utilisant 3 bibliothèques gratuites différentes, rien ne s'affiche dans l'écran de disposition. Le logcat répète le message suivant:

 W / Trace (1378): valeur inattendue de nativeGetEnabledTags: 0
 I / Chorégraphe (1378): 55 images sautées! L'application fait peut-être trop de travail sur son thread principal.

Le problème n'a pas persisté et le graphique a fonctionné lorsque j'ai exécuté un exemple de code se rapportant à une copie d'évaluation d'une bibliothèque sous licence.


2
Dessinez-vous vos graphiques sur un fil distinct?
Areks

Merci pour votre commentaire, j'ai modifié la question pour la rendre plus claire. L'activité lors de l'exécution montre que j'exécute une activité qui n'a pas de conception de sa mise en page => montrant un écran blanc.
user2038135

1
@Areks Non, je n'utilise pas de fil distinct.
user2038135

1
Je pense que vous devriez, n'est pas recommandé du tout d'effectuer de longues opérations sur le thread principal, car cela gèle toute l'application, vous pouvez lire comment utiliser les threads ici: stackoverflow.com/questions/3391272/… Ignorez le "code à faire la requête HTTP "et exécutez simplement vos opérations potentiellement longues.
Areks

1
Pourquoi vous n'essayez pas de chercher, vous trouverez des informations sur le chorégraphe. Je vous recommande de lire cette réponse: stackoverflow.com/questions/11266535/…
Gabriel Esteban

Réponses:


479

extrait de: Android UI: Correction des cadres sautés

Quiconque commence à développer une application Android voit ce message sur logcat «Chorégraphe (abc): cadres xx ignorés! L'application fait peut-être trop de travail sur son thread principal. " Alors qu'est-ce que cela signifie réellement, pourquoi devriez-vous vous inquiéter et comment le résoudre?

Cela signifie que votre code prend beaucoup de temps à traiter et que les cadres sont ignorés à cause de cela, peut-être à cause d'un traitement lourd que vous effectuez au cœur de votre application ou de l'accès DB ou de toute autre chose qui provoque le thread à arrêtez-vous un moment.

Voici une explication plus détaillée:

Le chorégraphe permet aux applications de se connecter au vsync et de planifier correctement les choses pour améliorer les performances.

Les animations de vue Android utilisent en interne Choreographer dans le même but: chronométrer correctement les animations et éventuellement améliorer les performances.

Étant donné que Choreographer est informé de tous les événements vsync, je peux savoir si l'un des Runnables transmis par le Choreographer.post * apis ne se termine pas en une seule image, entraînant l'omission d'images.

À ma connaissance, le chorégraphe ne peut détecter que le saut de trame. Il n'a aucun moyen de dire pourquoi cela se produit.

Le message "L'application fait peut-être trop de travail sur son thread principal." pourrait être trompeur.

source: Signification des messages du chorégraphe dans Logcat

Pourquoi vous devriez vous inquiéter

Lorsque ce message apparaît sur l'émulateur Android et que le nombre d'images sautées est assez petit (<100), vous pouvez parier que l'émulateur est lent - ce qui se produit presque tout le temps. Mais si le nombre d'images sautées et grandes et de l'ordre de 300+, il peut y avoir de sérieux problèmes avec votre code. Les appareils Android sont livrés dans une vaste gamme de matériel contrairement aux appareils iOS et Windows. La RAM et le CPU varient et si vous voulez des performances et une expérience utilisateur raisonnables sur tous les appareils, vous devez résoudre ce problème. Lorsque les trames sont ignorées, l'interface utilisateur est lente et décalée, ce qui n'est pas une expérience utilisateur souhaitable.

Comment le réparer

Pour résoudre ce problème, il faut identifier les nœuds où il y a ou peut se produire une longue durée de traitement. La meilleure façon est de faire tout le traitement, peu importe sa taille, dans un thread séparé du thread d'interface utilisateur principal. Donc, que ce soit en accédant au formulaire de données SQLite Database ou en faisant des calculs hardcore ou simplement en triant un tableau - Faites-le dans un thread différent

Maintenant, il y a un hic ici, vous allez créer un nouveau thread pour effectuer ces opérations et lorsque vous exécutez votre application, il se bloque en disant "Seul le thread d'origine qui a créé une hiérarchie de vues peut toucher ses vues". Vous devez savoir que l'interface utilisateur dans Android peut être modifiée uniquement par le thread principal ou le thread d'interface utilisateur. Tout autre thread qui tente de le faire, échoue et se bloque avec cette erreur. Ce que vous devez faire est de créer un nouveau Runnable à l'intérieur de runOnUiThread et à l'intérieur de ce runnable, vous devez effectuer toutes les opérations impliquant l'interface utilisateur. Trouvez un exemple ici .

Nous avons donc Thread et Runnable pour le traitement des données hors du thread principal, quoi d'autre? Il y a AsyncTask dans Android qui permet de faire des processus de longue durée sur le thread d'interface utilisateur. C'est le plus utile lorsque vos applications sont pilotées par les données ou les API Web ou que vous utilisez des interfaces utilisateur complexes comme celles créées à l'aide de Canvas. La puissance d'AsyncTask est qu'elle permet de faire des choses en arrière-plan et une fois que vous avez terminé le traitement, vous pouvez simplement effectuer les actions requises sur l'interface utilisateur sans provoquer d'effet de retard. Cela est possible car AsyncTask dérive lui-même du thread d'interface utilisateur de l'activité - toutes les opérations que vous effectuez sur l'interface utilisateur via AsyncTask sont effectuées est un thread différent du thread d'interface utilisateur principal, aucune entrave à l'interaction avec l'utilisateur.

C'est donc ce que vous devez savoir pour créer des applications Android fluides et pour autant que je sache, chaque débutant reçoit ce message sur sa console.


41
J'ai juste une application où si je clique sur un bouton, l'image d'arrière-plan du bouton change et le bouton ne peut pas être cliqué. Comment je fais trop de travail :(
Remian8985

1
@ Remian8985 - La modification de l'image d'arrière-plan du bouton (en supposant que vous téléchargez cette image) doit être effectuée dans une AsyncTask - c'est-à-dire effectuer cette opération d'arrière-plan de téléchargement et publier le résultat sur le thread d'interface utilisateur (fournir l'image en arrière). Voir le lien de
BenJaminSila

11
@BenJaminSila change d'arrière-plan dans AsyncTask? Vraiment?
user25

11
@ user25 "en supposant que vous téléchargez cette image"
forresthopkinsa

"Lorsque ce message apparaît sur l'émulateur Android et que le nombre d'images sautées est assez petit (<100), vous pouvez parier que l'émulateur est lent". Cela s'applique-t-il encore aujourd'hui? Les émulateurs deviennent assez rapides non?
Robin Dijkhof

243

Comme d'autres ont répondu ci-dessus, "55 images ignorées!" signifie qu'un traitement lourd est dans votre application.

Pour mon cas, il n'y a pas de processus lourd dans ma demande. J'ai tout vérifié et vérifié trois fois et supprimé ces processus, je pense que c'était un peu lourd.

J'ai supprimé des fragments, des activités, des bibliothèques jusqu'à ce qu'il ne reste que le squelette. Mais le problème n'a toujours pas disparu. J'ai décidé de vérifier les ressources et j'ai trouvé que certaines icônes et arrière-plans que j'utilise sont assez gros car j'ai oublié de vérifier la taille de ces ressources.

Donc, ma suggestion est que si aucune des réponses ci-dessus ne vous aide, vous pouvez également vérifier la taille de vos fichiers de ressources.


1
A également fonctionné pour moi. J'avais une application qui faisait très peu de travail mais qui était lente et lente. J'ai continué à obtenir des journaux de cadres ignorés. Une fois que j'ai retiré l'arrière-plan de mon activité, tout allait bien. Merci!
akrabi

Excellente réponse, je crois que c'était exactement mon problème. J'ai essayé un tas d'autres solutions (assez impliquées) et l'application était tout aussi lente. J'ai supprimé tous les services Web et j'ai essayé d'optimiser mon code dans les moindres détails. Ça n'a pas marché, alors j'ai vu ça. Dès que j'ai supprimé mon image de fond (la plus grande image que j'ai), l'application fonctionne aussi vite que vous pouvez cliquer sur des éléments, même avec l'ancien code "lent".
M Barbosa

tu as fait ma journée!
Nicolas Mastromarino

:) Vous êtes un génie absolu.
Metin Ilhan

@batsheva il n'est pas nécessaire d'être 1 Ko. Cela dépend de vos besoins, disons que vous avez besoin d'une image plus claire, vous pouvez utiliser une résolution plus élevée, mais assurez-vous de vous diviser en différentes tailles dans les différents dossiers de ressources.
Sithu

61

Moi aussi, j'ai eu le même problème.
Le mien était un cas où j'utilisais une image d'arrière-plan qui était en dessinable.Cette image particulière était d'environ 130 Ko et a été utilisée pendant l'écran de démarrage et la page d'accueil dans mon application Android.

Solution - Je viens de déplacer cette image particulière dans le dossier drawables-xxx à partir de drawables et j'ai pu libérer beaucoup de mémoire occupée en arrière-plan et les cadres à sauter ne sautaient plus.

Mise à jour Utilisez le dossier de ressources dessinables «nodp» pour stocker les fichiers dessinables en arrière-plan.
Est-ce qu'un classeur à tirage qualifié de densité ou un dessin à nodules tirables aura priorité?


7
J'ai déplacé ma grande image d'arrière-plan de dessinable vers mimap-xxxhdpi et cela a fait l'affaire!
bgplaya

Tu as beaucoup aidé. Merci
N.Droid

2
Cette solution fait l'affaire. J'utilise drawable-xxxhdpiplutôt un dossier, drawablece qui réduit considérablement la mémoire utilisée (~ 70% de moins). Aussi bon à savoir, les écrans de même taille varient en taille DPI. Le rapport en pixels entre eux est ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. En utilisant le drawable-xxxhdpidossier, vous permettez de réduire l'échelle des images à la taille d'écran de votre appareil, ce qui réduit la consommation de mémoire et de processeur.
Timo Bähr

2
Le déplacement d'images de drawableà drawable-nodpiempêche l'application de se récupérer Out of Memory Error.
Shruti

Oh mon dieu ... merci! J'avais une image dans le dossier dessinable et cela a rendu mon application lente comme l'enfer (bien que l'image ne soit que 100 Ko !!!). Après avoir généré les fichiers drawable-xxx (j'ai utilisé l'importateur Android Drawable) mon application est sacrément rapide. Merci beaucoup!
error1337

20

Une autre cause courante de retards sur le thread d'interface utilisateur est l'accès SharedPreferences. Lorsque vous appelez une PreferenceManager.getSharedPreferenceset d'autres méthodes similaires pour la première fois, le fichier .xml associé est immédiatement chargé et analysé dans le même thread .

L'une des bonnes façons de lutter contre ce problème consiste à déclencher la première charge SharedPreference à partir du thread d'arrière-plan, démarrée le plus tôt possible (par exemple à partir onCreatede votre classe Application). De cette façon, l'objet de préférence peut être déjà construit au moment où vous souhaitez l'utiliser.

Malheureusement, la lecture d'un fichier de préférences est parfois nécessaire lors des premières phases de démarrage (par exemple dans l'activité initiale ou même dans l'application elle-même). Dans de tels cas, il est toujours possible d'éviter le blocage de l'interface utilisateur en utilisant MessageQueue.IdleHandler. Faites tout ce que vous devez effectuer sur le thread principal, puis installez le IdleHandler pour exécuter le code une fois que votre activité a été entièrement dessinée. Dans ce Runnable, vous devriez pouvoir accéder à SharedPreferences sans retarder trop d'opérations de dessin et rendre Choreographer mécontent.


1
Dans ce cas, vous devriez préférer la méthode apply () au lieu de commit (). La méthode apply () ne peut pas bloquer l'interface utilisateur. Vous pouvez regarder ici developer.android.com/training/data-storage/shared-preferences
Emre Gürses

16

Essayez d'utiliser les stratégies suivantes afin d'améliorer les performances de votre application:

  • Utilisez la programmation multi-thread si possible. Les avantages en termes de performances sont énormes, même si votre téléphone intelligent a un cœur (les threads peuvent s'exécuter dans différents cœurs, si le processeur en a deux ou plus). Il est utile de séparer la logique de votre application de l'interface utilisateur. Utilisez des threads Java, AsyncTask ou IntentService. Vérifiez ça .
  • Lisez et suivez les conseils de performances divers du site Web de développement Android. Vérifiez ici .

3
votre premier lien nécessite que vous "... ayez un compte validé ..." pour y accéder.
chornge

9

J'ai eu le même problème. L'émulateur Android a parfaitement fonctionné sur Android <6.0. Lorsque j'ai utilisé l'émulateur Nexus 5 (Android 6.0), l'application fonctionnait très lentement avecI/Choreographer: Skipped frames dans les journaux.

J'ai donc résolu ce problème en modifiant l' hardwareAcceleratedoption de fichier Manifest pour trueaimer ceci:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application android:hardwareAccelerated="true">
        ...
    </application>
</manifest>

8

Je ne suis pas un expert, mais j'ai reçu ce message de débogage lorsque je voulais envoyer des données de mon application Android à un serveur Web. Bien que j'aie utilisé la classe AsyncTask et effectué le transfert de données en arrière-plan, pour récupérer les données de résultat du serveur, j'ai utilisé la méthode get () de la classe AsyncTask qui rend l'interface utilisateur synchrone, ce qui signifie que votre interface utilisateur attendra trop longtemps. Mon conseil est donc de faire en sorte que votre application effectue toutes les tâches orientées réseau sur un thread séparé.


6

Optimisez vos images ... N'utilisez pas d'images de plus de 100 Ko ... Le chargement d'images prend trop de CPU et provoque le blocage de votre application.


4
Réduire la taille de l' image soit par code java ou photoshop utiliser pour rogner des images .. aussi compresser des images en utilisant compressor.io
HarshitG

5

J'ai eu le même problème. Dans mon cas, j'avais 2 dispositions relatives imbriquées. RelativeLayout doit toujours effectuer deux passes de mesure. Si vous imbriquez RelativeLayouts, vous obtenez un algorithme de mesure exponentielle.


4

cela se produit généralement lorsque vous exécutez d'énormes processus dans le thread principal. il est possible d'ignorer les images inférieures à 200. mais si vous avez plus de 200 images ignorées, cela peut ralentir le thread d'interface utilisateur de votre application. ce que vous pouvez faire est de faire ces processus dans un nouveau thread appelé thread de travail et après cela, lorsque vous voulez accéder et faire qq avec le thread d'interface utilisateur (ex: faire quelque chose avec les vues, findView etc ...), vous pouvez utiliser le gestionnaire ou runOnUiThread (J'aime plus ça) afin d'afficher les résultats du traitement. cela résout absolument le problème. l'utilisation de threads de travail est très utile ou doit même être utilisée dans ce cas.


1

J'ai eu le même problème. Lorsque j'ai exécuté le code sur un autre ordinateur, cela a bien fonctionné. Sur le mien, cependant, il affiche "L'application peut faire trop de travail sur son thread principal".

J'ai résolu mon problème en redémarrant Android studio [Fichier -> Caches / Redémarrage invalides -> cliquez sur "Invalider et redémarrer"].


Je ne sais pas pourquoi votre solution a fonctionné. Quoi qu'il en soit merci.
Bhuvanesh BS

1

Dans mon cas, c'est parce que j'avais accidentellement défini un point d'arrêt sur une méthode. Une fois que je l'ai effacé, le message a disparu et les performances se sont beaucoup améliorées.


0

Mon application a eu le même problème. Mais il ne faisait rien d'autre que d'afficher la liste des cartes et du texte dessus. Rien ne tourne en arrière-plan. Mais après, une enquête a révélé que l'image définie pour le fond de la carte était à l'origine de cela, même si elle était petite (350 Ko). Ensuite, j'ai converti l'image en images 9patch en utilisant http://romannurik.github.io/AndroidAssetStudio/index.html .
Cela a fonctionné pour moi.


0

Après avoir fait beaucoup de R&D sur ce problème, j'ai obtenu la solution,

Dans mon cas, j'utilise un service qui fonctionnera toutes les 2 secondes et avec le runonUIThread, je me demandais si le problème était là mais pas du tout. Le problème suivant que j'ai trouvé est que j'utilise une grande image dans l'application May et c'est le problème.

J'ai supprimé les images et défini de nouvelles images.

Conclusion: - Regardez dans votre code s'il y a un fichier brut que vous utilisez est de grande taille.


0

Lisez d'abord l'avertissement. Il indique plus de charge sur le thread principal. Donc, ce que vous avez à faire est d'exécuter simplement des fonctions avec plus de travail dans un thread.


-1

J'ai eu le même problème lors du développement d'une application qui utilise beaucoup de fichiers png dessinables sur la disposition de la grille. J'ai également essayé d'optimiser mon code autant que possible .. mais cela n'a pas fonctionné pour moi .. Ensuite, j'ai essayé de réduire la taille de ces png .. et je suppose que cela fonctionne très bien .. Donc ma suggestion est de réduire taille des ressources utilisables, le cas échéant.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.