La manière dont vous gérez la hiérarchie de vos objets View
peut avoir un impact important sur les performances de votre application. Cette page explique comment évaluer si votre hiérarchie des vues ralentit votre application et propose quelques stratégies pour résoudre les problèmes qui peuvent survenir.
Mise en page et mesure des performances
Le pipeline de rendu comprend une étape de mise en page et de mesure, au cours de laquelle le système positionne correctement les éléments pertinents dans votre hiérarchie des vues. La phase de mesure de cette étape détermine la taille et les limites des objets View
. La phase de mise en page détermine l'emplacement des objets View
sur l'écran.
Ces deux étapes de pipeline entraînent un faible coût par vue ou mise en page qu'elles traitent. La plupart du temps, ce coût est minime et n'affecte pas sensiblement les performances. Il peut toutefois être plus élevé lorsqu'une application ajoute ou supprime des objets View, par exemple lorsqu'un objet RecyclerView
les recycle ou les réutilise. Le coût peut également être plus élevé s'il faut envisager de redimensionner l'objet View
pour répondre à ses contraintes. Par exemple, si votre application appelle SetText()
sur un objet View
qui encapsule le texte, vous devrez peut-être redimensionner la View
.
Si ce type de cas prend trop de temps, il peut empêcher une image de s'afficher dans les 16 ms autorisées. Par conséquent, des images sont supprimées et la lecture est saccadée.
Étant donné que vous ne pouvez pas déplacer ces opérations vers un thread de nœud de calcul (votre application doit les traiter sur le thread principal), la meilleure solution consiste à les optimiser afin qu'elles prennent le moins de temps possible.
Gestion de la complexité : les mises en page sont importantes
Les mises en page Android vous permettent d'imbriquer des objets d'interface utilisateur dans la hiérarchie des vues. Cette imbrication peut également entraîner un coût de mise en page. Lorsque votre application traite un objet pour mise en page, elle effectue également le même processus sur tous les enfants de la mise en page. Lorsque la mise en page est complexe, un coût n'est parfois généré que la première fois que le système calcule la mise en page. Par exemple, lorsque votre application recycle un élément de liste complexe dans un objet RecyclerView
, le système doit mettre en page tous les objets. Dans un autre exemple, des modifications mineures peuvent se propager à la chaîne menant au parent jusqu'à ce qu'elles atteignent un objet qui n'affecte pas la taille du parent.
Le plus souvent, la mise en page prend beaucoup de temps lorsque des hiérarchies d'objets View
sont imbriquées. Chaque objet de mise en page imbriqué ajoute un coût à l'étape de mise en page. Plus votre hiérarchie est plate, moins l'étape de mise en page prend du temps.
Si vous utilisez la classe RelativeLayout
, vous pouvez obtenir le même effet à moindre coût en utilisant des vues LinearLayout
imbriquées et non pondérées. En outre, si votre application cible Android 7.0 (niveau d'API 24), vous pouvez probablement utiliser un éditeur de mise en page spécial pour créer un objet ConstraintLayout
au lieu de RelativeLayout
. Cela vous permet d'éviter de nombreux problèmes décrits dans cette section. La classe ConstraintLayout
offre un contrôle de mise en page similaire, mais avec des performances nettement améliorées. Cette classe utilise son propre système de résolution des contraintes pour résoudre les relations entre les vues d'une manière très différente des mises en page standard.
Double imposition
En règle générale, le framework exécute l'étape de mise en page ou de mesure en une seule fois et assez rapidement. Toutefois, dans certains cas plus complexes, il est possible que le framework doive itérer plusieurs fois sur les parties de la hiérarchie qui nécessitent une résolution en plusieurs passes avant de positionner les éléments. L'exécution de plusieurs itérations de mise en page et de mesure s'appelle la double imposition.
Par exemple, lorsque vous utilisez le conteneur RelativeLayout
, qui vous permet de positionner des objets View
par rapport aux positions d'autres objets View
, le framework effectue les actions suivantes :
- Exécute une passe de mise en page et de mesure au cours de laquelle le framework calcule la position et la taille de chaque objet enfant, en fonction de la requête de chaque enfant.
- Utilise ces données en tenant également compte des pondérations des objets pour déterminer la position correcte des vues corrélées.
- Effectue une deuxième mise en page pour finaliser la position des objets.
- Passe à l'étape suivante du processus de rendu.
Plus votre hiérarchie est vaste, plus la pénalité liée aux performances est élevée.
Les conteneurs autres que RelativeLayout
peuvent également entraîner une double imposition. Exemple :
- Une vue
LinearLayout
peut entraîner une double passe de mise en page et de mesure si vous la rendez horizontale. Un double passe de mise en page et de mesure peut également se produire dans une orientation verticale si vous ajoutez : measureWithLargestChild, auquel cas le framework devra effectuer une seconde passe pour résoudre les tailles d'objets appropriées. - Le
GridLayout
pose un problème similaire. Bien que ce conteneur permet également un positionnement relatif, il évite normalement la double imposition en prétraitant les relations de position entre les vues enfants. Toutefois, si la mise en page utilise des pondérations ou un remplissage avec la classeGravity
, l'avantage de ce prétraitement est perdu, et le framework devra peut-être effectuer plusieurs passes si le conteneur était unRelativeLayout
.
L'utilisation de plusieurs passes de mise en page et de mesure ne constitue pas en soi un obstacle aux performances. Mais elles peuvent le devenir si elles ne sont pas au bon endroit. Méfiez-vous des situations où l'une des conditions suivantes s'applique à votre conteneur :
- Il s'agit d'un élément racine dans la hiérarchie des vues.
- Il est sous-hiérarchique.
- Il remplit de nombreuses instances, comme les enfants dans un objet
ListView
.
Diagnostiquer les problèmes de hiérarchie des vues
Les performances de mise en page sont un problème complexe aux multiples facettes. Il existe plusieurs outils qui peuvent vous donner des indications précises sur les endroits où des goulots d'étranglement affectent les performances. D'autres outils fournissent des informations moins directes, mais peuvent également fournir des indications utiles.
Systrace
Systrace est l'un des outils qui fournissent d'excellentes données sur les performances, intégré au SDK Android. L'outil Systrace vous permet de collecter et de vérifier les informations temporelles sur un appareil Android dans son intégralité, ce qui vous permet de savoir à quel moment les problèmes de mise en page entraînent des problèmes de performances. Pour en savoir plus sur Systrace, consultez la présentation du traçage système.
Rendu GPU du profil
L'autre outil susceptible de vous fournir des informations concrètes sur les goulots d'étranglement qui affectent les performances est l'outil de rendu GPU du profil sur l'appareil. Il est disponible sur les appareils équipés d'Android 6.0 (niveau d'API 23) et versions ultérieures. Cet outil vous permet de savoir combien de temps prend l'étape de mise en page et de mesure pour chaque image du rendu. Ces données peuvent vous aider à diagnostiquer les problèmes de performances liés à l'exécution et à déterminer les éventuels problèmes de mise en page et de mesure à résoudre.
Dans sa représentation graphique des données capturées, le rendu de GPU du profil utilise la couleur bleue pour représenter le temps de mise en page. Pour en savoir plus sur l'utilisation de cet outil, consultez la présentation du rendu GPU du profil.
Lint
L'outil lint d'Android Studio peut vous aider à identifier les problèmes d'efficacité dans la hiérarchie des vues. Pour utiliser cet outil, sélectionnez Analyze > Inspect Code (Analyser > Inspecter le code), comme indiqué dans la figure 1.

Figure 1 : Localisation de l'option Inspect Code (Inspecter le code) dans Android Studio.
Les informations sur les différents éléments de mise en page s'affichent sous Android > Lint > Performance. Pour afficher plus de détails, vous pouvez cliquer sur chaque élément pour le développer et afficher plus d'informations dans le volet situé à droite de l'écran. La figure 2 est un exemple de ce type d'écran.

Figure 2 : Afficher des informations sur des problèmes spécifiques identifiés par l'outil lint.
Cliquez sur l'un de ces éléments pour afficher le problème associé dans le volet de droite.
Pour en savoir plus sur des sujets et des problèmes spécifiques dans cette zone, consultez la documentation lint.
Outil d'inspection de la mise en page
L'outil d'inspection de la mise en page d'Android Studio fournit une représentation visuelle de la hiérarchie des vues de votre application. C'est un bon moyen de naviguer dans la hiérarchie de votre application. Il offre une représentation visuelle claire de la chaîne parente d'une vue spécifique et vous permet d'inspecter les mises en page construites par votre application.
Les vues proposées par l'outil d'inspection de la mise en page peuvent également vous aider à identifier les problèmes de performances liés à la double imposition. L'outil peut aussi vous permettre d'identifier facilement les chaînes profondes de mises en page imbriquées, ou les zones de mise en page avec un grand nombre d'enfants imbriqués, qui peuvent engendrer des coûts de performances. Dans ces scénarios, les étapes de mise en page et de mesure peuvent s'avérer particulièrement coûteuses, ce qui entraîne des problèmes de performances.
Pour en savoir plus, consultez Déboguer la mise en page avec l'outil d'inspection de la mise en page.
Résoudre les problèmes liés à la hiérarchie des vues
Le concept fondamental qui sous-tend la résolution des problèmes de performances découlant des hiérarchies des vues est simple en théorie, mais plus complexe dans la pratique. Pour empêcher les hiérarchies des vues d'imposer des pénalités de performances, il faut viser les deux objectifs suivants : aplatir la hiérarchie des vues et réduire la double imposition. Cette section présente certaines stratégies qui permettent d'atteindre ces objectifs.
Supprimer les mises en page imbriquées redondantes
Les développeurs utilisent souvent plus de mises en page imbriquées que nécessaire. Par exemple, un conteneur RelativeLayout
peut contenir un seul enfant, qui est également un conteneur RelativeLayout
. Cette imbrication équivaut à une redondance, et ajoute un coût inutile à la hiérarchie des vues.
Lint peut signaler ce problème pour vous, réduisant ainsi le temps de débogage.
Fusionner/Inclure
L'une des causes fréquentes de redondances liées aux mises en page imbriquées est la balise <include>. Par exemple, vous pouvez définir une mise en page réutilisable comme suit :
<LinearLayout> <!-- some stuff here --> </LinearLayout>
Ajoutez ensuite une balise « include » pour ajouter cet élément au conteneur parent :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg" android:gravity="center_horizontal"> <include layout="@layout/titlebar"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" /> ... </LinearLayout>
La balise imbrique inutilement la première mise en page dans la seconde.
La balise merge peut vous aider à éviter ce problème. Pour en savoir plus sur cette balise, consultez Réutiliser des mises en page avec <include>.
Adopter une mise en page moins chère
Vous ne pourrez peut-être pas ajuster votre mise en page existante afin qu'elle ne contienne pas de mises en page redondantes. Dans certains cas, la seule solution peut être d'aplatir votre hiérarchie en basculant vers un type de mise en page complètement différent.
Par exemple, vous constaterez peut-être qu'une propriété TableLayout
offre les mêmes fonctionnalités qu'une mise en page plus complexe avec de nombreuses dépendances de position. Dans la version N d'Android, la classe ConstraintLayout
offre des fonctionnalités semblables à celles de RelativeLayout
, mais pour un coût nettement inférieur.