Modo de omisión seguro

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 optables.
  • Las lambdas con capturas inestables se recuerdan.

Cómo habilitar el modo de omisión avanzada

El omitición sólida está habilitada de forma predeterminada en Kotlin 2.0.20.

Para habilitar el omitición estricta de 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
}

Omisión de elementos componibles

El modo de omisión fuerte relaja algunas de las reglas de estabilidad que suele aplicar el compilador de Compose cuando se trata de omitir funciones y funciones componibles. 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.

Con la omisión sólida habilitada, todas las funciones de componibilidad reiniciables se pueden omitir. Esto se aplica independientemente de si tienen parámetros inestables o no. Las funciones de componibilidad que no se pueden reiniciar no se pueden omitir.

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 desees que un elemento componible inhabilite el omitición fuerte. Es decir, es posible que desees un elemento componible reiniciable, pero que no se pueda omitir. En este caso, usa la anotación @NonSkippableComposable.

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

Cómo anotar clases como estables

Si deseas que un objeto use la igualdad de objetos en lugar de la igualdad de instancias, continúa anotando la clase determinada con @Stable. Un ejemplo de cuándo podrías tener que hacer esto es cuando observas una lista completa de objetos. Las fuentes de datos, como Room, asignarán objetos nuevos para cada elemento de la lista cada vez que uno de ellos cambie.

Memorización de Lambda

El modo de omisión avanzada también habilita más memoización de lambdas dentro de los elementos componibles. Si habilitas la omisión avanzada, se recordará automáticamente cada lambda dentro de una función de componibilidad.

Ejemplos

Para lograr la memorización de lambdas dentro de los elementos componibles cuando se usa el omitir forzado, el compilador une tu lambda con una llamada a remember. Se codifica con las capturas de la lambda.

Considera un caso en el que tienes una 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 almacena en caché la 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 claves inestables con igualdad de instancias. Compara claves estables con 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ónomite 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 elemento componible 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 memoización

Si tienes una expresión lambda que no deseas almacenar en caché, 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 elementos componibles que no se pueden omitir. Con la omisión sólida habilitada, el compilador marca casi todos los elementos componibles como omitibles y une todas las lambdas en un remember{...}. Debido a esto, habilitar el modo de omisión avanzada tiene un impacto muy pequeño en el tamaño del APK de tu aplicación.

Habilitar el omitir forzado 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 no se podían omitir anteriormente y que estaban presentes en la app determinada, pero debería ser relativamente menor.