Diagnosticar problemas de estabilidade

Se você estiver com problemas de desempenho resultantes de erros recomposição excessiva, é necessário depurar a estabilidade do seu app. Este guia descreve vários métodos para fazer isso.

Layout Inspector

O Layout Inspector no Android Studio permite conferir quais elementos combináveis são de recomposição no seu app. Ela mostra quantas vezes o Compose recompor ou ignorar um componente.

Contagens de recomposição e pulos no Layout Inspector

Relatórios do compilador do Compose

O compilador do Compose pode gerar os resultados da inferência de estabilidade para inspeção. Usando essa saída, é possível determinar quais elementos combináveis são puláveis e quais não são. As subseções a seguir resumem como usar essas mas para informações mais detalhadas consulte a documentação técnica Documentação.

Configurar

Os relatórios do compilador do Compose não são ativados por padrão. Você pode ativá-los com um flag de compilador. A configuração exata varia de acordo com seu projeto, mas, em projetos que usam o plug-in do Gradle para compilador do Compose, você pode adicione o seguinte em cada arquivo build.gradle dos módulos:

  android { ... }

  composeCompiler {
    reportsDestination = layout.buildDirectory.dir("compose_compiler")
    metricsDestination = layout.buildDirectory.dir("compose_compiler")
  }

Os relatórios do compilador do Compose agora serão gerados ao criar seu projeto.

Exemplo de saída

O reportsDestination gera três arquivos. Veja a seguir exemplos de saídas do JetSnack.

  • <modulename>-classes.txt:um relatório sobre a estabilidade das classes neste mais tarde neste módulo. Exemplo.
  • <modulename>-composables.txt:um relatório sobre o quanto é possível reiniciar e (puláveis) dos elementos combináveis estão no módulo. Exemplo.
  • <modulename>-composables.csv:uma versão CSV do relatório de elementos combináveis. que você pode importar para uma planilha ou processar usando um script. Exemplo
.

Relatório de elementos combináveis

O arquivo composables.txt detalha cada função combinável para o do módulo, incluindo a estabilidade de seus parâmetros e se eles são reinicializável ou pulável. Veja a seguir um exemplo hipotético JetSnack:

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
  stable snackCollection: SnackCollection
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
  stable index: Int = @static 0
  stable highlight: Boolean = @static true
)

Esse elemento SnackCollection pode ser reiniciado, ser ignorado e o estábulo. Geralmente, isso é preferível, embora certamente não seja obrigatório.

Por outro lado, vamos analisar outro exemplo.

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  unstable snacks: List<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

O elemento combinável HighlightedSnacks não é pulável. O Compose nunca a ignora durante a recomposição. Isso vai acontecer mesmo que nenhum dos parâmetros tenha sido alterado. O motivo é o parâmetro unstable, snacks.

Relatório de turmas

O arquivo classes.txt contém um relatório semelhante sobre as classes do mais tarde neste módulo. O snippet abaixo é a saída da classe Snack:

unstable class Snack {
  stable val id: Long
  stable val name: String
  stable val imageUrl: String
  stable val price: Long
  stable val tagline: String
  unstable val tags: Set<String>
  <runtime stability> = Unstable
}

Para referência, esta é a definição de Snack:

data class Snack(
    val id: Long,
    val name: String,
    val imageUrl: String,
    val price: Long,
    val tagline: String = "",
    val tags: Set<String> = emptySet()
)

O compilador do Compose marcou Snack como instável. Isso ocorre porque o tipo de o parâmetro tags for Set<String>. Esse é um tipo imutável, porque não é um MutableSet. No entanto, as classes de coleção padrão, como Set, List, e Map são interfaces. Assim, a implementação subjacente pode ainda pode ser mutável.

Por exemplo, seria possível escrever val set: Set<String> = mutableSetOf("foo"). A variável é constante e seu tipo declarado não é mutável, mas sua implementação ainda é mutável. O compilador do Compose não pode ter certeza da imutabilidade dessa classe, já que ela vê apenas o tipo declarado. Portanto, ela marca tags como instável.