Por que os pesos aninhados são ruins para o desempenho? Alternativas?

160

Escrevi alguns arquivos de layout em que usei o layout_weightatributo para criar uma proporção entre diferentes visualizações.

Em algum momento, começo a receber avisos sobre pesos aninhados.

Então, eu me pergunto por que os pesos aninhados são ruins para o desempenho e se existe uma maneira mais eficiente de criar uma proporção constante entre as dimensões da visualização que podem ser usadas para diferentes tamanhos de tela e que não precisam especificar muitos valores de dpi da dimensão através de vários arquivos de layout (para diferentes tamanhos de tela, quero dizer).

Obrigado!

MobileCushion
fonte
2
Uma publicação incrível para Otimização de layout developer.android.com/training/improving-layouts/…
Muhammad Babar 4/13

Respostas:

140

Pesos aninhados são ruins para o desempenho porque:

Os pesos do layout exigem que um widget seja medido duas vezes. Quando um LinearLayout com pesos diferentes de zero é aninhado dentro de outro LinearLayout com pesos diferentes de zero, o número de medições aumenta exponencialmente.

É melhor usar RelativeLayout se ajustar sua visualização de acordo com os locais de outras visualizações sem usar valores de dpi específicos.

CD
fonte
87
É bom estar ciente, o que suponho ser o objetivo da mensagem. Eu iria notar que um impacto exponencial ainda é pequena se o expoente envolvido é pequeno. Para pequenas profundidades de aninhamento, não usar a CPU necessária para fazer isso é como ter um cavalo de trabalho que você mima durante toda a semana e que só faz caminhadas aos domingos. Ainda assim, para grandes profundidades de nidificação, é um ponto bem considerado.
Carl
14
O RelativeLayout também precisa ser medido duas vezes para garantir o layout correto de todos os filhos, portanto, altere LinearLayout com peso do layout para RelativeLayout pode não melhorar o desempenho.
Piasy
O layout relativo nem sempre funciona. Nos casos em que você precisa construir widgets proporcionais
Abdurakhmon
67

Atualização: como sabemos, a porcentagem de biblioteca de suporte foi descontinuada do nível 26 da API. ConstraintLayoutÉ a nova maneira de obter a mesma estrutura xml plana.

Projeto Github atualizado

Amostras atualizadas:

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

Atualização: Ótimas notícias na biblioteca de suporte percentual do Android resolve nosso problema de desempenho e o peso aninhado e aninhadoLinearLayout

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

Demonstração AQUI

Considere este layout simples para demonstrar o mesmo.

por cento de suporte à demonstração da biblioteca

<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 desempenho evitado aninhado LinearLayoutcom pesos.Realmente incrível !!!.

nitesh
fonte
@dan Sim, considerando que aninhamos o layout linear com pesos.
Nitesh
3
"Esta classe foi descontinuada no nível da API 26.0.0-beta1. Considere o uso de ConstraintLayout e layouts associados." developer.android.com/reference/android/support/percent/…
saiyancoder
7
Eu não gosto de ConstraintLayout. Ele não se comporta de forma intuitiva para mim
Carson Holzheimer
8
o ConstraintLayout é tão difícil para mim
BertKing
1
talvez as explicações dadas pela apple sobre as restrições de reprodução automática sejam mais claras e, como a lógica é a mesma, ela pode ajudar. Infelizmente, acho o ConstraintLayout do droid mais pesado / detalhado do que o iOS 'AutoLayout
AdricoM
46

Eu acho (e provavelmente serei inflamado por isso), mas, novamente, acho que meu telefone tem um processador quad core para rivalizar (se não destruir completamente) os PCs domésticos da maioria das pessoas.

Eu também acho que esse tipo de capacidade de hardware é o futuro dos telefones.

Portanto, chego à conclusão de que, desde que você não se empolgue com o aninhamento (no MHO, um layout nunca deve ter mais de quatro níveis de profundidade e, se é que você provavelmente está fazendo errado), seu telefone pode se importar menos sobre ter pesos.

Há muitas coisas que você pode fazer que terão um efeito muito mais abrangente no desempenho e, em seguida, se preocupem com o processador fazendo algumas contas extras.

(observe que estou sendo um pouco humorístico e, portanto, para não levar nada muito a sério nesta postagem, a ideia de que há outras coisas que você deve otimizar primeiro e de que se preocupar com um peso profundo de 2 a 3 níveis não está ajudando sua saúde)

WIllJBD
fonte
2
tomadas e essencialmente concordam, mas ouviram falar do uso médio do iPhone (incluindo os serviços / site da Web que o suportam) em torno da mesma quantidade de energia por ano que a geladeira comum nos EUA. Portanto, é nossa responsabilidade como desenvolvedores levar esse tipo de impacto ambiental em consideração. Obviamente, é sempre um ato de equilíbrio: tempo, custos, desempenho, estabilidade e geralmente concordo com a sua perspectiva - mas pense que devemos considerar também esse tipo de impacto. Obviamente, a manutenção / extensibilidade também vem aqui. De qualquer forma - ponto feito e obrigado.
MemeDeveloper
Perceba que o ponto específico em questão é sobre o processamento no dispositivo e não na Web, mas quero dizer meu comentário como um ponto geral sobre prioridades como desenvolvedores, mais do que detalhes do OP.
MemeDeveloper
11

A principal razão pela qual os pesos aninhados são ruins é que, quando um layout tem filhos com peso, ele deve ser medido duas vezes (acho que isso é mencionado no aviso de fiapos). Isso significa que um layout ponderado que também contém um layout ponderado deve ser medido quatro vezes e cada 'camada' de pesos que você adiciona aumenta as medidas com uma potência de dois.

No ICS (nível API 14), GridLayoutfoi adicionado o que permite soluções simples e "planas" para muitos layouts que anteriormente exigiam pesos. Se você está desenvolvendo para versões anteriores do Android, terá mais dificuldade em remover pesos, mas usar RelativeLayoute achatar o máximo possível de seu layout na cabine normalmente remove muitos pesos aninhados.

Jave
fonte
9
Eu não acho que você pode obter os mesmos resultados com GridLayout ou RelativeLayout . Por exemplo, para GridLayout: "GridLayout não oferece suporte ao princípio de peso, conforme definido em peso. Em geral, não é possível configurar um GridLayout para distribuir espaço em excesso entre vários componentes".
Timmmm
A partir da API 21, a noção de peso foi adicionada ao GridLayout. Para oferecer suporte a dispositivos Android mais antigos, você pode usar o GridLayout da biblioteca de suporte da v7. android.support.v7.widget.GridLayout
# Evansgelist Evansgelist 10/09/15
2

Existe uma solução fácil para evitar LinearLayouts aninhados com pesos - basta usar Tablelayout com weightSum e LinearLayout aninhado com weightSum - O Tablelayout possui os mesmos atributos que LinearLayout (orientação, weightSum, layout_weight etc.) e não mostra a mensagem - "pesos aninhados tem ruim para o desempenho "

Exemplo:

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

Penso que a única alternativa é criar uma função que seria chamada onResume e definirá todos os tamanhos e posições. De qualquer forma, em peso, você pode definir apenas tamanhos, mas sem preenchimento (para que os layouts se tornem ainda mais complicados), sem tamanho de texto (impossível de compensar isso de alguma forma), sem falar em número de linhas.

Gangnus
fonte