La omisión avanzada es un modo disponible en el compilador de Compose. Cuando está habilitado, cambia el comportamiento del compilador de dos maneras:
- Los elementos componibles con parámetros inestables se vuelven omitibles.
- Las lambdas con capturas inestables se recuerdan.
Habilita el modo de omisión avanzada
La omisión estricta está habilitada de forma predeterminada en Kotlin 2.0.20.
Para habilitar la omisión estricta en un módulo de Gradle en una versión anterior a la 2.0.20, incluye la siguiente opción en el bloque composeCompiler de tu configuración de Gradle:
android { ... }
composeCompiler {
enableStrongSkippingMode = true
}
Posibilidad de omitir elementos componibles
El modo de omisión estricto flexibiliza algunas de las reglas de estabilidad que normalmente aplica el compilador de Compose cuando se trata de omisiones y funciones de componibilidad. De forma predeterminada, el compilador de Compose marca una función de componibilidad como omitible si todos sus argumentos tienen valores estables. El modo de omisión avanzada cambia esto.
Cuando se habilita la omisión sólida, todas las funciones de componibilidad reiniciables se vuelven omitibles. Esto se aplica independientemente de si tienen parámetros inestables o no. Las funciones de componibilidad que no se pueden reiniciar siguen sin poder omitirse.
Cuándo omitir
Para determinar si se debe omitir un elemento componible durante la recomposición, Compose compara el valor de cada parámetro con sus valores anteriores. El tipo de comparación depende de la estabilidad del parámetro.
- Los parámetros inestables se comparan con la igualdad de instancias (
===). - Los parámetros estables se comparan con la igualdad de objetos (
Object.equals()).
Si todos los parámetros cumplen con estos requisitos, Compose omite el elemento componible durante la recomposición.
Es posible que quieras que un elemento componible inhabilite la omisión sólida. Es decir, es posible que quieras un elemento componible reiniciable, pero que no se pueda omitir. En este caso, usa la anotación @NonSkippableComposable.
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}
Anota las clases como estables
Si quieres que un objeto se compare con la igualdad de objetos (Object.equals()) en lugar de la igualdad de instancias (===), sigue anotando la clase determinada con @Stable o @Immutable.
Ten en cuenta las siguientes compensaciones antes de agregar @Stable o @Immutable:
- Las clases con propiedades estables en los módulos de Compose ya son estables: Una clase con propiedades
valde tipos estables en un módulo compilado con el compilador de Compose se infiere automáticamente como estable y usa.equals()sin necesidad de@Immutableni@Stable. - Solo anota clases con verificaciones
.equals()económicas: Agrega@Stableo@Immutablecuando el compilador no pueda inferir la estabilidad (como las clases de módulos que no son de Compose) y se asignen con frecuencia instancias nuevas con valores idénticos, siempre que la verificación.equals()de la clase sea económica. - Ten cuidado cuando anotes modelos con colecciones: Agregar
@Stableo@Immutablea modelos que contienen colecciones (o reemplazarListporImmutableList) hace que Compose compare cada elemento de la colección con.equals()en cada pase de recomposición. En el caso de colecciones o modelos grandes que se usan en diseños diferidos (LazyColumn,LazyRow,LazyGrid), comparar cada elemento puede ser más lento que usar la igualdad de instancias (===) o volver a componer directamente.
Memoización de lambdas
El modo de omisión avanzada también habilita más memorización de lambdas dentro de los elementos componibles. Con la omisión avanzada habilitada, se recordará automáticamente cada expresión lambda dentro de una función de componibilidad.
Ejemplos
Para lograr la memorización de lambdas dentro de elementos componibles cuando se usa la omisión estricta, el compilador une tu lambda con una llamada a remember. Se asocia con las capturas de la lambda.
Considera un caso en el que tienes una expresión lambda como en el siguiente ejemplo:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = {
use(unstableObject)
use(stableObject)
}
}
Con la omisión avanzada habilitada, el compilador memoriza la expresión lambda uniéndola en una llamada a remember:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = remember(unstableObject, stableObject) {
{
use(unstableObject)
use(stableObject)
}
}
}
Las claves siguen las mismas reglas de comparación que las funciones de componibilidad. El entorno de ejecución compara las claves inestables con la igualdad de instancias. Compara claves estables con la igualdad de objetos.
Memoización y recomposición
Esta optimización aumenta en gran medida la cantidad de elementos componibles que el entorno de ejecución omite durante la recomposición. Sin la memorización, es mucho más probable que el entorno de ejecución asigne una lambda nueva a cualquier función de componibilidad que tome un parámetro lambda durante la recomposición. Como resultado, la nueva lambda tiene parámetros que no son iguales a los de la última composición. Esto genera una recomposición.
Evita la memorización
Si tienes una expresión lambda que no quieres memorizar, usa la anotación @DontMemoize.
val lambda = @DontMemoize {
...
}
Tamaño del APK
Cuando se compilan, los elementos componibles que se pueden omitir generan más código que los que no se pueden omitir. Con la omisión sólida habilitada, el compilador
marca casi todos los elementos componibles como que se pueden omitir y une todas las lambdas en un
remember{...}. Por lo tanto, habilitar el modo de omisión avanzada tiene un impacto muy pequeño en el tamaño del APK de tu aplicación.
Habilitar la omisión sólida en Now in Android aumentó el tamaño del APK en 4 kB. La diferencia de tamaño depende en gran medida de la cantidad de elementos componibles que antes no se podían omitir y que estaban presentes en la app determinada, pero debería ser relativamente menor.