Cuando se encuentra con una clase inestable que provoca rendimiento problemas, debes hacerlo estable. En este documento, se describen varias técnicas puedes usar para hacerlo.
Habilitar la omisión fuerte
Primero, debes intentar habilitar el modo de omisión intensa. Modo de omisión fuerte Permite que se omitan los elementos componibles con parámetros inestables y es la opción más sencilla método para solucionar problemas de rendimiento causados por la estabilidad.
Consulta Omisiones fuertes para obtener más información.
Haz que la clase sea inmutable
También puedes intentar hacer que una clase inestable sea completamente inmutable.
- Inmutable: Indica un tipo en el que el valor de cualquier propiedad nunca puede.
cambian después de que se construye una instancia de ese tipo, y todos los métodos
transparente como referencia.
- Asegúrate de que todas las propiedades de la clase sean
val
en lugar devar
. y de tipos inmutables. - Los tipos primitivos, como
String, Int
yFloat
, son siempre inmutables. - Si esto es imposible, debes usar el estado de Compose para cualquier propiedad mutable.
- Asegúrate de que todas las propiedades de la clase sean
- Estable: Indica un tipo que es mutable. El entorno de ejecución de Compose no saber si cualquiera de las propiedades o métodos públicos del tipo daría como resultado resultados diferentes a los de una invocación previa.
Colecciones inmutables
Un motivo común por el que Compose considera que una clase es inestable son las colecciones. Como se indicó anteriormente
en la página Diagnostica problemas de estabilidad, el compilador de Compose
no podemos estar completamente seguros de que las colecciones como List, Map
y Set
sean
realmente inmutables y, por lo tanto, los marca como inestables.
Para resolver esto, puedes usar colecciones inmutables. El compilador de Compose incluye compatibilidad con las colecciones inmutables de Kotlinx. Estos se garantiza que las colecciones sean inmutables, y el compilador de Compose las trata. como tal. Esta biblioteca aún se encuentra en versión alfa, de modo que se pueden producir posibles cambios en su API.
Considera nuevamente esta clase inestable de la página Diagnosticar estabilidad problemas:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
Puedes hacer que tags
sea estable con una colección inmutable. En la clase, cambia
tipo de tags
a ImmutableSet<String>
:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
Después de hacerlo, todos los parámetros de la clase son inmutables, y Compose el compilador marca la clase como estable.
Anota con Stable
o Immutable
Una posible ruta para resolver los problemas de estabilidad es anotar las clases inestables.
con @Stable
o @Immutable
.
La anotación de una clase anula lo que, de otro modo, el compilador
inferir sobre tu clase. Es similar al
Operador !!
en Kotlin Deberías ser muy
ten cuidado con el uso de estas anotaciones. Anula el comportamiento del compilador
podría generar errores imprevistos, como que el elemento componible no se vuelva a componer cuando
esperas que lo haga.
Si es posible hacer que tu clase sea estable sin una anotación, deberías esforzarse por lograr la estabilidad de esa manera.
El siguiente fragmento proporciona un ejemplo mínimo de una clase de datos anotada como inmutable:
@Immutable
data class Snack(
…
)
Ya sea que uses la anotación @Immutable
o @Stable
, el compilador de Compose
marca la clase Snack
como estable.
Clases con anotaciones en colecciones
Considera un elemento componible que incluya un parámetro de tipo List<Snack>
:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
Incluso si anotas Snack
con @Immutable
, el compilador de Compose seguirá marcando el elemento.
el parámetro snacks
en HighlightedSnacks
como inestable
Los parámetros enfrentan el mismo problema que las clases
cuando se trata de tipos de colecciones
El compilador de Compose siempre marca un parámetro de tipo List
como inestable, incluso
cuando es una colección de tipos estables.
No puedes marcar un parámetro individual como estable, ni puedes anotar una componibles para que siempre se puedan omitir. Hay varios caminos a seguir.
Existen varias formas de solucionar el problema de las recopilaciones inestables. Estos diferentes enfoques se describen en las siguientes subsecciones.
Archivo de configuración
Si deseas cumplir con el contrato de estabilidad de tu base de código,
puedes optar por considerar las colecciones de Kotlin como estables agregando
kotlin.collections.*
a tu
archivo de configuración de estabilidad.
Colección inmutable
Para la seguridad del tiempo de compilación de la inmutabilidad, puedes
usa una colección inmutable de kotlinx, en lugar de List
.
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
Si no puedes usar una colección inmutable, puedes crear una propia. Para ello, sigue estos pasos:
une List
en una clase estable con anotaciones. Un wrapper genérico probablemente sea el
la mejor opción para esto según tus requisitos.
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
Luego, puedes usar esto como el tipo de parámetro en el elemento componible.
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
Solución
Después de adoptar cualquiera de estos enfoques, el compilador de Compose ahora marca el
HighlightedSnacks
Se puede componer como skippable
y restartable
.
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
stable snacks: ImmutableList<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
Durante la recomposición, Compose ahora puede omitir HighlightedSnacks
si ninguno de sus
cambiaron las entradas.
Archivo de configuración de estabilidad
A partir de Compose Compiler 1.5.5, un archivo de configuración de clases para
se pueden obtener durante el tiempo de compilación. Esto permite considerar
clases que no controlas, como clases de biblioteca estándar
como LocalDateTime
, como estable.
El archivo de configuración es un archivo de texto sin formato con una clase por fila. Comentarios, se admiten comodines individuales y dobles. A continuación, se muestra un ejemplo de configuración:
// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>
Para habilitar esta función, pasa la ruta de acceso del archivo de configuración a Compose opciones del compilador.
Groovy
kotlinOptions {
freeCompilerArgs += [
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
project.absolutePath + "/compose_compiler_config.conf"
]
}
Kotlin
kotlinOptions {
freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
"${project.absolutePath}/compose_compiler_config.conf"
)
}
A medida que el compilador de Compose se ejecuta en cada módulo de tu proyecto por separado, puedes proporcionar diferentes configuraciones a diferentes módulos si es necesario. También puedes tener uno de Terraform en el nivel raíz de tu proyecto y pasa esa ruta de acceso a cada módulo.
Varios módulos
Otro problema habitual es la arquitectura de varios módulos. El compilador de Compose solo puede inferir si una clase es estable si todos los tipos no primitivos que sus referencias están marcadas explícitamente como estables o en un módulo que también se compiló con el compilador de Compose.
Si la capa de datos está en un módulo separado de la capa de la IU, que es el enfoque recomendado, es posible que tenga este problema.
Solución
Para resolver este problema, puedes adoptar uno de los siguientes enfoques:
- Agrega las clases a tu archivo de configuración del compilador.
- Habilita el compilador de Compose en tus módulos de capas de datos o etiqueta tus clases.
con
@Stable
o@Immutable
cuando corresponda.- Esto implica agregar una dependencia de Compose a tu capa de datos. Sin embargo,
Es solo la dependencia del entorno de ejecución de Compose y no
Compose-UI
- Esto implica agregar una dependencia de Compose a tu capa de datos. Sin embargo,
Es solo la dependencia del entorno de ejecución de Compose y no
- Dentro del módulo de tu IU, une las clases de capas de datos en un wrapper específico de la IU .
El mismo problema también ocurre cuando se usan bibliotecas externas si no utilizan la Compilador de Compose.
No todos los elementos componibles se deben omitir
Cuando trabajas para solucionar problemas de estabilidad, no debes tratar de hacer elemento componible que se puede omitir. Si intentas hacerlo, es posible que la optimización sea prematura que introduce más problemas de los que corrige.
Hay muchas situaciones en las que la opción de omitir el anuncio no tiene ningún beneficio real y pueden dificultar el mantenimiento de un código. Por ejemplo:
- Un elemento componible que no se recompone con frecuencia (o en absoluto).
- Un elemento componible que por sí solo llama a elementos que se pueden omitir
- Un elemento componible con una gran cantidad de parámetros con equivalencias costosas de Google Cloud. En este caso, el costo de verificar si algún parámetro tiene podría superar el costo de una recomposición económica.
Cuando un elemento componible se puede omitir, agrega una pequeña sobrecarga que puede no valer la pena. que la modifica. Incluso puedes anotar el elemento componible para que no se pueda reiniciar en los casos. que determina que la capacidad de reiniciarse implica más sobrecarga de lo que merece la pena.