Otimizar hierarquias de layout

Teste o Compose
O Jetpack Compose é o kit de ferramentas de interface recomendado para Android. Aprenda a trabalhar com layouts no Compose.

É um erro comum achar que usar as estruturas básicas de layout leva a layouts mais eficientes. No entanto, cada widget e layout que você adiciona ao app exige inicialização, layout e desenho. Por exemplo, o uso de instâncias aninhadas de LinearLayout pode levar a uma hierarquia de visualização excessivamente profunda. Além disso, aninhar várias instâncias de LinearLayout que usam o parâmetro layout_weight pode ser especialmente caro, porque cada filho precisa ser medido duas vezes. Isso é especialmente importante quando o layout é inflado repetidamente, como quando usado em um RecyclerView.

Este documento mostra como usar o Layout Inspector e o lint para examinar e otimizar o layout.

Inspecionar o layout

As Ferramentas do SDK do Android incluem a ferramenta Layout Inspector, que permite analisar o layout enquanto o app está em execução. O uso dessa ferramenta ajuda a descobrir ineficiências na performance do layout.

O Layout Inspector permite selecionar processos em execução em um dispositivo ou emulador conectado e, em seguida, exibir a árvore de layout. Os semáforos em cada bloco representam a performance de medição, layout e desenho, ajudando a identificar possíveis problemas.

Por exemplo, a Figura 1 mostra um layout que é usado como item em uma RecyclerView. Esse layout mostra uma pequena imagem em bitmap à esquerda e dois itens de texto empilhados à direita. É especialmente importante que layouts como esse, que são inflados várias vezes, sejam otimizados, porque os benefícios de performance são multiplicados.

Uma imagem mostrando um único item em uma lista: uma imagem e dois textos alinhados verticalmente
Figura 1. Layout conceitual para um item em uma RecyclerView.

O Layout Inspector mostra uma lista de dispositivos disponíveis e os componentes em execução. Escolha o componente na guia Windows e clique em Layout Inspector para conferir a hierarquia de layout do componente selecionado. Por exemplo, a Figura 2 mostra o layout do item de lista ilustrado pela Figura 1.

Uma imagem mostrando o Layout Inspector e a composição do LinearLayout
Figura 2. Hierarquia do layout da Figura 1, que usa instâncias aninhadas de LinearLayout.

Revisar o layout

Como o desempenho anterior do layout fica mais lento devido a um LinearLayout aninhado, você pode melhorar a performance nivelando o layout, ou seja, tornando-o raso e amplo, em vez de estreito e profundo. Um ConstraintLayout como nó raiz permite esses layouts. Quando você converte esse design para usar ConstraintLayout, o layout se torna uma hierarquia de dois níveis:

    <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/root"
      android:layout_width="match_parent"
      android:layout_height="52dp"
      android:background="#e4e6e4"
      android:padding="4dp">

      <ImageView
          android:id="@+id/image"
          android:layout_width="48dp"
          android:layout_height="48dp"
          android:background="#5c5c74"
          android:contentDescription="An example box"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />

      <TextView
          android:id="@+id/title"
          android:layout_width="0dp"
          android:layout_height="0dp"
          android:layout_marginStart="4dp"
          android:background="#745c74"
          app:layout_constraintBottom_toTopOf="@+id/subtitle"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toEndOf="@id/image"
          app:layout_constraintTop_toTopOf="parent" />

      <TextView
          android:id="@+id/subtitle"
          android:layout_width="0dp"
          android:layout_height="0dp"
          android:background="#7e8d6e"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="@id/title"
          app:layout_constraintTop_toBottomOf="@+id/title" />
  </androidx.constraintlayout.widget.ConstraintLayout>
    

A inspeção do novo layout vai ficar assim:

Imagem mostrando o 3D Layout Inspector
Figura 3. Modo 3D do Layout Inspector.

Os benefícios são multiplicados, porque esse layout é usado para todos os itens de uma lista.

A maior parte da diferença se deve ao uso de layout_weight no design LinearLayout, o que pode atrasar a medição. Esse é um exemplo de como cada layout tem usos apropriados. Considere cuidadosamente se o uso do peso do layout é necessário.

Em alguns layouts complexos, o sistema pode perder esforço medindo o mesmo elemento da interface mais de uma vez. Esse fenômeno é chamado de dupla tributação. Para mais informações sobre a tributação dupla e como evitá-la, consulte Hierarquias de desempenho e visualização.

Usar lint

É recomendável executar a ferramenta lint nos arquivos de layout para procurar possíveis otimizações de hierarquia de visualização. O lint substitui a ferramenta layoutopt e tem mais funcionalidade. Veja a seguir exemplos de regras de lint:

  • Usar drawables compostos. É possível processar um LinearLayout que contenha um ImageView e um TextView com mais eficiência como um drawable composto.
  • Mesclar frame raiz. Se a raiz de um layout for um FrameLayout que não fornece plano de fundo ou preenchimento, você pode substituí-lo por uma tag de mesclagem, que é um pouco mais eficiente.
  • Remova folhas inúteis. Você pode remover um layout que não tem filhos ou plano de fundo (já que é invisível) para ter uma hierarquia de layout mais plana e mais eficiente.
  • Remover pais inúteis. Você pode remover um layout com um filho que não tenha irmãos, que não seja um ScrollView ou um layout raiz e não tenha um plano de fundo. Você também pode mover a visualização filha diretamente para a mãe para ter uma hierarquia de layout mais plana e eficiente.
  • Evite layouts profundos. Layouts com muito aninhamento prejudicam o desempenho. Considere usar layouts mais planos, como ConstraintLayout, para melhorar o desempenho. A profundidade máxima padrão das verificações de lint é 10.

Outro benefício da ferramenta lint é a integração com o Android Studio. O lint é executado automaticamente sempre que você compila o programa. Com o Android Studio, você também pode executar inspeções de lint para uma variante de build específica ou para todas as variantes de build.

Você também pode gerenciar perfis de inspeção e configurar inspeções no Android Studio com a opção File > Settings > Project Settings. A página "Inspection Configuration" é mostrada com as inspeções compatíveis:

Uma imagem mostrando o menu de inspeção do Android Studio
Figura 4. página de configuração da inspeção.

O lint pode corrigir automaticamente alguns problemas, fornecer sugestões para outros e pular diretamente para o código ofensivo para revisão.

Para mais informações, consulte Layouts e Recurso de layout.