O Compose considera que os tipos são estáveis ou instáveis. Um tipo é estável quando é imutável ou se é possível que o Compose saiba se o valor dele mudou entre as recomposições. Um tipo é instável quando o Compose não consegue saber se o valor mudou entre as recomposições.
O Compose usa a estabilidade dos parâmetros de um elemento combinável para determinar se ele pode ignorar o elemento durante a recomposição:
- Parâmetros estáveis:se um elemento combinável tiver parâmetros estáveis que não foram modificados, o Compose os ignorará.
- Parâmetros instáveis:quando um elemento combinável tem parâmetros instáveis, o Compose sempre faz a recomposição do pai do componente.
Caso seu app inclua muitos componentes desnecessariamente instáveis que o Compose sempre recompõe, é possível que você observe problemas de desempenho e outros problemas.
Este documento explica como aumentar a estabilidade do app para melhorar o desempenho e a experiência geral do usuário.
Objetos imutáveis
Os snippets abaixo demonstram os princípios gerais por trás de estabilidade e recomposição.
A classe Contact
é imutável. Isso ocorre porque todos os
parâmetros são primitivos definidos com a palavra-chave val
. Depois de criar uma
instância do Contact
, não é possível alterar o valor das propriedades do objeto.
Se você tentar fazer isso, crie um novo objeto.
data class Contact(val name: String, val number: String)
O elemento combinável ContactRow
tem um parâmetro do tipo Contact
.
@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
var selected by remember { mutableStateOf(false) }
Row(modifier) {
ContactDetails(contact)
ToggleButton(selected, onToggled = { selected = !selected })
}
}
Considere o que acontece quando o usuário clica no botão de ativação e o
estado selected
muda:
- O Compose avalia se precisa recompor o código dentro de
ContactRow
. - Ela vê que o único argumento para
ContactDetails
é do tipoContact
. - Como
Contact
é uma classe de dados imutável, o Compose tem certeza de que nenhum dos argumentos deContactDetails
mudou. - Como tal, o Compose ignora a
ContactDetails
e não a recompõe. - Por outro lado, os argumentos de
ToggleButton
mudaram, e o Compose faz a recomposição desse componente.
Objetos mutáveis
O exemplo anterior usa um objeto imutável, mas é possível criar um objeto mutável. Considere este snippet:
data class Contact(var name: String, var number: String)
Como cada parâmetro de Contact
agora é um var
, a classe não é mais imutável.
Se as propriedades mudassem, o Compose não ficaria ciente. Isso ocorre porque
o Compose só rastreia mudanças nos objetos de estado do Compose.
O Compose considera essa classe instável. O Compose não pula a recomposição de
classes instáveis. Dessa forma, se Contact
fosse definido dessa maneira, ContactRow
no exemplo anterior seria recomposto sempre que selected
mudasse.
Implementação no Compose
Pode ser útil, embora não crucial, considerar como exatamente o Compose determina quais funções serão ignoradas durante a recomposição.
Quando o compilador do Compose é executado no código, ele marca cada função e tipo com uma das várias tags. Essas tags refletem como o Compose processa a função ou o tipo durante a recomposição.
Funções
O Compose pode marcar funções como skippable
ou restartable
. Observe que ele pode
marcar uma função como uma, ambas ou nenhuma delas:
- Pulável: se o compilador marcar um elemento combinável como pulável, o Compose poderá pular durante a recomposição se todos os argumentos forem iguais aos valores anteriores.
- Reiniciável: um elemento combinável que pode ser reiniciado serve como um "escopo" em que a recomposição pode ser iniciada. Em outras palavras, a função pode ser um ponto de entrada em que o Compose pode começar a executar novamente o código para recomposição após as mudanças de estado.
Tipos
O Compose marca os tipos como imutáveis ou estáveis. Cada tipo é um ou outro:
- Imutável: o Compose marca um tipo como imutável se o valor das
propriedades nunca pode mudar e todos os métodos são referencialmente transparentes.
- Todos os tipos primitivos são marcados como imutáveis. Eles incluem
String
,Int
eFloat
.
- Todos os tipos primitivos são marcados como imutáveis. Eles incluem
- Estável: indica um tipo cujas propriedades podem mudar após a construção. Se e quando essas propriedades mudarem durante a execução, o Compose vai identificar essas mudanças.
Depurar a estabilidade
Se o app estiver recompondo um elemento combinável cujos parâmetros não foram modificados, primeiro
verifique a definição para conferir se há parâmetros claramente mutáveis. O Compose sempre
recompõe um componente se você transmitir um tipo com propriedades var
ou uma propriedade
val
que usa um tipo instável conhecido.
Para informações detalhadas sobre como diagnosticar problemas complexos com estabilidade no Compose, consulte o guia Depurar a estabilidade.
Corrigir problemas de estabilidade
Para informações sobre como trazer estabilidade à implementação do Compose, consulte o guia Corrigir problemas de estabilidade.
Resumo
No geral, você deve observar os seguintes pontos:
- Parâmetros: o Compose determina a estabilidade de cada parâmetro dos elementos combináveis para determinar quais elementos ele precisa pular durante a recomposição.
- Correções imediatas: se você perceber que a função combinável não está sendo ignorada e
está causando um problema de desempenho, verifique primeiro as causas óbvias de
instabilidade, como parâmetros
var
. - Relatórios do compilador: use os relatórios do compilador para determinar qual estabilidade está sendo inferida sobre suas classes.
- Coleções: o Compose sempre considera as classes de coleção instáveis, como
List, Set
eMap
. Isso ocorre porque não é possível garantir que eles sejam imutáveis. Você pode usar coleções imutáveis do Kotlinx ou anotar suas classes como@Immutable
ou@Stable
. - Outros módulos: o Compose sempre considera instáveis quando eles vêm de módulos em que o compilador do Compose não é executado. Una as classes em classes de modelo de interface, se necessário.
Leia mais
- Desempenho: para mais dicas de depuração sobre o desempenho do Compose, consulte nosso guia de práticas recomendadas e a palestra sobre o I/O.