O modo de rejeição avançada está disponível no compilador do Compose. Quando ativado, ele muda o comportamento do compilador de duas maneiras:
- Elementos combináveis com parâmetros instáveis podem ser pulados.
- As lambdas com capturas instáveis são gravadas
Ativar o modo de rejeição avançada
A omissão forte é ativada por padrão no Kotlin 2.0.20.
Para ativar o salto forte para um módulo do Gradle em uma versão anterior à 2.0.20,
inclua a seguinte opção no
bloco composeCompiler
da configuração do Gradle:
android { ... }
composeCompiler {
enableStrongSkippingMode = true
}
Recurso pulável combinável
O modo de pular forte relaxa algumas das regras de estabilidade normalmente aplicadas pelo compilador do Compose quando se trata de pular e funções combináveis. Por padrão, o compilador do Compose marca uma função combinável como pular se todos os argumentos tiverem valores estáveis. O modo de rejeição avançada muda isso.
Com a omissão forte ativada, todas as funções combináveis reiniciáveis se tornam omitíveis. Isso vale mesmo que eles tenham parâmetros instáveis. As funções combináveis não reiniciáveis continuam sem poder ser puladas.
Quando pular
Para determinar se um elemento combinável será ignorado durante a recomposição, o Compose compara o valor de cada parâmetro com os valores anteriores. O tipo de comparação depende da estabilidade do parâmetro.
- Os parâmetros instáveis são comparados usando a igualdade de instância (
===
). - Os parâmetros estáveis são comparados usando a igualdade de objetos (
Object.equals()
).
Se todos os parâmetros atenderem a esses requisitos, o Compose vai pular o combinável durante a recomposição.
Talvez você queira que um elemento combinável desative a omissão forte. Ou seja, você pode
querer um elemento combinável reiniciável, mas não pulado. Nesse caso, use a
anotação @NonSkippableComposable
.
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}
Anotar classes como estáveis
Se você quiser um objeto usando igualdade de objeto em vez de igualdade de instância,
continue a anotar a classe especificada com @Stable
.
Um exemplo de quando você pode
precisar fazer isso é ao observar uma lista inteira de objetos. As fontes de dados, como
o Room, vão alocar novos objetos para cada item da lista sempre que um deles
mudar.
Memorização Lambda
O modo de rejeição avançada também permite mais memorização de lambdas dentro de elementos combináveis. Com a rejeição avançada ativada, cada lambda dentro de uma função combinável é lembrada automaticamente.
Exemplos
Para alcançar a memorização de lambdas dentro de elementos combináveis ao usar o salto forte,
o compilador envolve a lambda com uma chamada remember
. Ele é codificado com as
capturas da lambda.
Considere um caso em que você tem uma lambda como no exemplo a seguir:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = {
use(unstableObject)
use(stableObject)
}
}
Com a rejeição avançada ativada, o compilador armazena em cache a lambda, envolvendo-a em
uma chamada remember
:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = remember(unstableObject, stableObject) {
{
use(unstableObject)
use(stableObject)
}
}
}
As chaves seguem as mesmas regras de comparação das funções combináveis. O ambiente de execução compara chaves instáveis usando a igualdade de instâncias. Ele compara chaves estáveis usando a igualdade de objetos.
Memoização e recomposição
Essa otimização aumenta muito o número de elementos combináveis que o ambiente de execução pula durante a recomposição. Sem a memorização, é muito mais provável que o ambiente de execução aloque uma nova lambda para qualquer elemento combinável que receba um parâmetro lambda durante a recomposição. Como resultado, a nova lambda tem parâmetros que não são iguais à última composição. Isso resulta na recomposição.
Evite a memorização
Se você tiver uma lambda que não quer armazenar em cache, use a anotação
@DontMemoize
.
val lambda = @DontMemoize {
...
}
Tamanho do APK
Quando compilados, os elementos combináveis que podem ser pulados resultam em mais código gerado do que
elementos combináveis que não podem ser pulados. Com o salto forte ativado, o compilador
marca quase todos os elementos combináveis como puláveis e envolve todos os lambdas em um
remember{...}
. Por isso, ativar o modo de rejeição avançada tem um impacto muito pequeno
no tamanho do APK do seu aplicativo.
Ativar o salto forte no Now In Android aumentou o tamanho do APK em 4 kB. A diferença no tamanho depende em grande parte do número de elementos combináveis não ignoráveis que estavam presentes no app, mas deve ser relativamente pequena.