web-dev-qa-db-fra.com

Pourquoi les poids imbriqués sont-ils mauvais pour la performance? Des alternatives?

J'ai écrit quelques fichiers de mise en page où j'ai utilisé le layout_weight attribut pour créer un rapport entre différentes vues.

À un moment donné, je commence à recevoir des avertissements contre les peluches concernant les poids imbriqués.

Je me demande donc pourquoi les poids imbriqués sont mauvais pour la performance et s'il existe un moyen plus efficace de créer un rapport constant entre les dimensions de la vue pouvant être utilisé pour différentes tailles d'écran sans qu'il soit nécessaire de spécifier beaucoup de valeurs de dimensions en dpi à travers plusieurs fichiers de mise en page (pour différentes tailles d’écran, je veux dire).

Je vous remercie!

152
MobileCushion

Les poids imbriqués sont mauvais pour la performance car:

Les poids de mise en page nécessitent qu'un widget soit mesuré deux fois. Lorsqu'un LinearLayout avec des poids non nuls est imbriqué dans un autre LinearLayout avec des poids non nuls, le nombre de mesures augmente de façon exponentielle.

Il vaut mieux utiliser RelativeLayout s et ajuster votre vue en fonction de l'emplacement des autres vues sans utiliser de valeurs de dpi spécifiques.

137
C.d.

Mise à jour: Comme nous le savons, la bibliothèque de support en pourcentage est obsolète à partir du niveau 26 de l'API. ConstraintLayout est le nouveau moyen d'obtenir le même code xml à plat. structure.

Projet Github mis à jour

Exemples mis à jour:

<Android.support.constraint.ConstraintLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <TextView
        Android:id="@+id/fifty_thirty"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:background="#ffff8800"
        Android:gravity="center"
        Android:text="@string/fifty_fifty_text"
        Android:textColor="@Android:color/white"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        Android:textSize="25sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:background="#ffff5566"
        Android:gravity="center"
        Android:text="@string/fifty_fifty_text"
        Android:textColor="@Android:color/white"
        Android:textSize="25sp"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintLeft_toRightOf="@id/fifty_thirty"
        app:layout_constraintTop_toBottomOf="@id/fifty_thirty"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

</Android.support.constraint.ConstraintLayout>

Mise à jour: Bonne nouvelle Android La bibliothèque de support résout notre problème de performances et de poids imbriqué en désordre LinearLayout

compile 'com.Android.support:percent:23.0.0'

démo ICI

Considérez cette disposition simple pour démontrer la même chose.

percent support libray demo

<Android.support.percent.PercentRelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">
    <TextView
        Android:id="@+id/fifty_huntv"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:background="#ff7acfff"
        Android:text="20% - 50%"
        Android:textColor="@Android:color/white"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="50%" />
    <TextView
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:layout_toRightOf="@id/fifty_huntv"
        Android:background="#ffff5566"
        Android:text="80%-50%"
        app:layout_heightPercent="80%"
        app:layout_widthPercent="50%"
        />

</Android.support.percent.PercentRelativeLayout>

Dégradé de la performance évitée imbriquée LinearLayout avec des poids. Vraiment génial !!!.

62
nitesh

Je pense (et je vais probablement être enflammé pour cela), mais encore une fois, je pense que mon téléphone a un processeur quad core pour rivaliser (sinon complètement détruire) la plupart des ordinateurs personnels domestiques.

Je pense aussi que ce type de capacité matérielle est l'avenir des téléphones.

J'arrive donc à la conclusion que tant que vous ne vous ennuyez pas avec l'imbrication (dans MHO, une disposition ne doit jamais être supérieure à 4 niveaux, et si c'est le cas, vous vous trompez probablement), votre téléphone s'en fiche d'avoir des poids.

Il y a beaucoup de choses que vous pouvez faire qui auront un effet beaucoup plus profond sur les performances, alors que vous vous inquiétez du temps que votre processeur fasse des calculs supplémentaires.

(Veuillez noter que je suis un peu humoristique et que je ne prends donc pas trop au sérieux ce billet. Autrement, il faut d'abord optimiser les choses, et s'inquiéter d'un poids de 2 ou 3 kilos n'est pas utile. votre santé)

44
WIllJBD

La principale raison pour laquelle les poids imbriqués sont incorrects est que, lorsqu'un modèle a des enfants avec un poids, il doit être mesuré deux fois (je pense que cela est mentionné dans l'avertissement de peluches). Cela signifie qu'une disposition pondérée qui contient également une disposition pondérée doit être mesurée quatre fois, et chaque "couche" de poids que vous ajoutez augmente les mesures avec une puissance de deux.

Dans ICS (niveau 14 de l'API), le GridLayout a été ajouté, ce qui permet d'offrir des solutions simples et "plates" pour de nombreuses dispositions qui nécessitaient auparavant une pondération. vous développez pour des versions antérieures de Android vous aurez un peu plus de mal à enlever les poids, mais vous utiliserez un RelativeLayout et vous ferez disparaître le plus possible de votre mise en page dans cette cabine. beaucoup de poids imbriqués.

10
Jave

Il existe une solution simple pour éviter les LinearLayouts imbriqués avec des poids - utilisez simplement Tablelayout avec weightSum et LinearLayout imbriqué avec weightSum - Tablelayout a les mêmes attributs que LinearLayout (orientation, weightSum, layout_weight, etc.) et ne affiche pas le message - "nested weights mauvais pour la performance "

Exemple:

 <TableLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical"
        Android:weightSum="1">

        <ImageView
            Android:layout_width="match_parent"
            Android:layout_height="0dp"
            Android:layout_weight="0.8"/>


        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="0dp"
            Android:layout_weight="0.2"
            Android:orientation="horizontal"
            Android:weightSum="1">


            <ImageView
                Android:layout_height="match_parent"
                Android:layout_width="0dp"
                Android:layout_weight="0.4"/>

            <TextView
                Android:layout_height="match_parent"
                Android:layout_width="0dp"
                Android:layout_weight="0.6"/>


            </LinearLayout>

    </TableLayout>
3
eneyovich

Je pense que la seule alternative est de créer une fonction qui s'appellerait onResume et définira toutes les tailles et positions. Quoi qu'il en soit, en poids, vous pouvez définir uniquement les tailles mais pas de rembourrage (donc les mises en page deviennent encore plus compliquées), pas de textSize (impossible de compenser cela d'une manière ou d'une autre), encore moins le nombre de lignes.

0
Gangnus