¿Por qué los pesos anidados son malos para el rendimiento? ¿Alternativas?

160

He escrito un par de archivos de diseño donde utilicé el layout_weightatributo para crear una relación entre diferentes vistas.

En algún momento, empiezo a recibir advertencias de pelusa sobre pesos anidados.

Entonces, me pregunto por qué los pesos anidados son malos para el rendimiento, y si hay una forma más eficiente de crear una relación constante entre las dimensiones de la vista que podría usarse para diferentes tamaños de pantalla y que no necesita especificar muchos valores de ppp de dimensión a través de varios archivos de diseño (quiero decir, para diferentes tamaños de pantalla).

¡Gracias!

Cojín Móvil
fuente
2
Una publicación impresionante para Layout Optimization developer.android.com/training/improving-layouts/…
Muhammad Babar

Respuestas:

140

Los pesos anidados son malos para el rendimiento porque:

Los pesos de diseño requieren que un widget se mida dos veces. Cuando un LinearLayout con pesos distintos de cero está anidado dentro de otro LinearLayout con pesos distintos de cero, el número de mediciones aumenta exponencialmente.

Es mejor usar RelativeLayout sy ajustar su vista de acuerdo con los lugares de otras vistas sin usar valores de dpi específicos.

Discos compactos
fuente
87
Es bueno tener en cuenta, que supongo que es el propósito del mensaje. Me gustaría señalar que un impacto exponencial sigue siendo pequeño si el exponente involucrado es pequeño. Para pequeñas profundidades de anidación, no usar la CPU necesaria para hacer esto es como tener un caballo de batalla que mimar durante toda la semana y solo salir a caminar los domingos. Aún así, para grandes profundidades de anidación, es un punto bien tomado.
Carl
14
RelativeLayout también necesita medir dos veces para asegurarse de que todo su diseño secundario sea adecuado, por lo que cambiar LinearLayout con peso de diseño a RelativeLayout puede no mejorar el rendimiento.
Piasy
El diseño relativo no siempre funciona. En los casos en que necesite construir widgets proporcionales
Abdurakhmon
67

Actualización: Como sabemos, el porcentaje de biblioteca de soporte está en desuso del nivel 26 de API. ConstraintLayoutEs la nueva forma de lograr la misma estructura plana de XML.

Proyecto Github actualizado

Muestras actualizadas:

<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>

Actualización: Buenas noticias, la biblioteca de soporte porcentual de Android resuelve nuestro problema de rendimiento y ponderado desordenado anidadoLinearLayout

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

Demo AQUÍ

Considere este diseño simple para demostrar lo mismo.

Porcentaje de soporte de demostración de libray

<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>

Degradador de rendimiento evitado anidado LinearLayoutcon pesas. ¡Realmente increíble!

nitesh
fuente
@dan Sí, teniendo en cuenta que tenemos un diseño lineal anidado con pesos.
nitesh
3
"Esta clase fue obsoleta en el nivel de API 26.0.0-beta1. Considere usar ConstraintLayout y diseños asociados en su lugar". developer.android.com/reference/android/support/percent/…
saiyancoder
77
No me gusta RestraintLayout. No se comporta intuitivamente para mí
Carson Holzheimer
8
el RestraintLayout es muy difícil para mí
BertKing
1
Tal vez las explicaciones dadas por Apple sobre las restricciones de auto-distribución son más claras, y como la lógica es la misma, puede ayudar. Desafortunadamente, me parece que el RestraintLayout de droid es más pesado / detallado que el
AutoLayout
46

Creo (y probablemente se me criticará por esto), pero de nuevo creo que mi teléfono tiene un procesador de cuatro núcleos para rivalizar (si no destruir por completo) la mayoría de las PC hogareñas.

También creo que este tipo de capacidad de hardware es el futuro de los teléfonos.

Así que llegué a la conclusión de que, siempre y cuando no te dejes llevar por la anidación (en MHO un diseño nunca debe tener más de 4 niveles de profundidad, y si es así, probablemente lo estés haciendo mal), a tu teléfono podría importarle menos sobre tener pesas.

Hay muchas cosas que puede hacer que tendrán un efecto mucho más amplio en el rendimiento, y luego se preocuparán de que su procesador realice algunas operaciones matemáticas adicionales.

(tenga en cuenta que estoy siendo un poco humorístico, por lo que no me tome demasiado en serio esta publicación, aparte de la idea de que hay otras cosas que debe optimizar primero, y que preocuparse por un peso profundo de 2-3 niveles no está ayudando tu salud)

WIllJBD
fuente
2
tomado, y esencialmente de acuerdo, pero he escuchado que el uso promedio del iPhone (incluidos los servicios web / sitio que lo respaldan) es aproximadamente la misma cantidad de energía al año que el refrigerador doméstico promedio de EE. UU. Por lo tanto, es nuestra responsabilidad como desarrolladores tener en cuenta este tipo de impacto ambiental. Obviamente, siempre es un acto de equilibrio: tiempo, costos, rendimiento, estabilidad y, en general, estoy de acuerdo con su perspectiva, pero creo que también deberíamos considerar este tipo de impacto. Obviamente, el mantenimiento / extensibilidad viene aquí también. De todos modos - hecho punto y gracias.
MemeDeveloper
Me doy cuenta de que el punto específico en cuestión es sobre el procesamiento en el dispositivo, no en la web, pero quiero decir mi comentario como un punto general sobre las prioridades como desarrolladores más que los detalles del OP.
MemeDeveloper
11

La razón principal por la cual los pesos anidados son malos es que cuando un diseño tiene hijos con un peso, debe medirse dos veces (creo que esto se menciona en la advertencia de pelusa). Esto significa que un diseño ponderado que también contiene un diseño ponderado tiene que medirse cuatro veces, y cada 'capa' de pesos que agrega aumenta las medidas con una potencia de dos.

En ICS (API nivel 14) GridLayoutse agregó, lo que permite soluciones simples y 'planas' para muchos diseños que anteriormente requerían pesos. Si está desarrollando versiones anteriores de Android, le resultará un poco más difícil eliminar los pesos, pero usar RelativeLayouty aplanar la mayor cantidad posible de su diseño en esa cabina generalmente elimina muchos de los pesos anidados.

Jave
fuente
9
No creo que puedas lograr los mismos resultados con GridLayout o RelativeLayout . Por ejemplo, para GridLayout: "GridLayout no proporciona soporte para el principio de peso, como se define en peso. En general, por lo tanto, no es posible configurar un GridLayout para distribuir el espacio en exceso entre múltiples componentes".
Timmmm
A partir de API 21, la noción de peso se agregó a GridLayout. Para admitir dispositivos Android más antiguos, puede usar GridLayout desde la biblioteca de soporte de v7. android.support.v7.widget.GridLayout
Эвансгелист Evansgelist
2

Hay una solución fácil para evitar LinearLayouts anidados con pesos: solo use Tablelayout con weightSum y LinearLayout anidado con weightSum: Tablelayout tiene los mismos atributos que LinearLayout (orientación, weightSum, layout_weight, etc.) y no muestra el mensaje "pesos anidados tener mal rendimiento "

Ejemplo:

 <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>
eneyovich
fuente
1

Creo que la única alternativa es hacer una función que se llame onResume y establecerá todos los tamaños y posiciones. De todos modos, por peso, puede establecer solo tamaños pero sin relleno (por lo que los diseños se vuelven aún más complicados), sin tamaño de texto (imposible de compensar esto de alguna manera), y mucho menos cosas como el número de líneas.

Gangnus
fuente