En cas d'utilisation d'une classe instable qui entraîne des performances les problèmes, vous devez le rendre stable. Ce document décrit plusieurs techniques que vous pouvez utiliser pour cela.
Activer les sauts fréquents
Vous devez d'abord essayer d'activer ce mode. Mode "Ignorer" de façon intensive permet d'ignorer les composables avec des paramètres instables. C'est l'option la plus simple pour résoudre les problèmes de performances causés par la stabilité.
Pour en savoir plus, consultez la section Ignorance fortement forte.
Rendre la classe immuable
Vous pouvez également essayer de rendre une classe instable complètement immuable.
- Immuable: indique un type dans lequel la valeur d'une propriété ne peut jamais
sont modifiés après la construction d'une instance de ce type et toutes les méthodes sont
de manière référentielle.
- Assurez-vous que toutes les propriétés de la classe sont
val
et nonvar
. et de types immuables. - Les types primitifs tels que
String, Int
etFloat
sont toujours immuables. - Si cela est impossible, vous devez utiliser l'état de Compose pour les propriétés modifiables.
- Assurez-vous que toutes les propriétés de la classe sont
- Stable: indique un type modifiable. L'environnement d'exécution Compose ne savoir si l'une des propriétés ou méthodes publiques du type entraînerait des résultats différents à partir d'un appel précédent.
Collections immuables
Les collections sont l'une des raisons courantes pour lesquelles Compose considère une classe comme instable. Comme indiqué
sur la page Diagnostiquer les problèmes de stabilité, le compilateur Compose
ne peut pas être sûr que les collections telles que List, Map
et Set
sont
vraiment immuables et les marque
donc comme instables.
Pour résoudre ce problème, vous pouvez utiliser des collections immuables. Compilateur Compose est compatible avec les collections immuables Kotlinx. Ces les collections sont immuables, et le compilateur Compose les traite en tant que tel. Cette bibliothèque étant encore en version alpha, attendez-vous à des modifications de son API.
Considérez à nouveau cette classe instable de l'atelier Diagnostiquer la stabilité problèmes:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
Vous pouvez rendre tags
stable à l'aide d'une collection immuable. Dans le cours, remplacez
Type de tags
sur ImmutableSet<String>
:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
Une fois cette opération effectuée, tous les paramètres de la classe sont immuables, et Compose le compilateur marque la classe comme stable.
Annoter avec Stable
ou Immutable
Pour résoudre les problèmes de stabilité, vous pouvez annoter les classes instables.
avec @Stable
ou @Immutable
.
L'annotation d'une classe remplace ce que le compilateur aurait autrement
déduire de votre classe. Elle est semblable à la
!!
en Kotlin. Vous devez être très
soyez prudent lorsque vous utilisez ces annotations. Remplacer le comportement du compilateur
peut entraîner des bugs imprévus, tels que votre composable qui ne se recompose pas
comme prévu.
S'il est possible de rendre votre classe stable sans annotation, vous devez s'efforcer d'atteindre la stabilité de cette façon.
L'extrait de code suivant fournit un exemple minimal de classe de données annotée en tant que immuables:
@Immutable
data class Snack(
…
)
Que vous utilisiez l'annotation @Immutable
ou @Stable
, le compilateur Compose
marque la classe Snack
comme stable.
Classes annotées dans les collections
Prenons l'exemple d'un composable qui inclut un paramètre de type List<Snack>
:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
Même si vous annotez Snack
avec @Immutable
, le compilateur Compose marque toujours
le paramètre snacks
dans HighlightedSnacks
comme étant instable.
Les paramètres sont confrontés au même problème que
les classes concernant les types de collections,
Le compilateur Compose marque toujours un paramètre de type List
comme instable, même
lorsqu'il s'agit d'un ensemble
de types stables.
Vous ne pouvez pas marquer un paramètre individuel comme stable, ni annoter un pour qu'il soit toujours ignorable. Il y a plusieurs façons d'avancer.
Il existe plusieurs façons de contourner le problème des collections instables. Ces différentes approches sont décrites dans les sous-sections suivantes.
Fichier de configuration
Si vous souhaitez respecter le contrat de stabilité dans votre codebase, alors
vous pouvez considérer les collections Kotlin comme stables en ajoutant
kotlin.collections.*
à votre
fichier de configuration de stabilité.
Collection immuable
Pour garantir l'immuabilité au moment de la compilation, vous pouvez
utilisez une collection immuable kotlinx au lieu de List
.
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
Si vous ne pouvez pas utiliser de collection immuable, vous pouvez créer la vôtre. Pour ce faire,
Encapsulez List
dans une classe stable annotée. Un wrapper générique est probablement
le meilleur choix en fonction de vos besoins.
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
Vous pouvez ensuite l'utiliser comme type de paramètre dans votre composable.
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
Solution
Après avoir adopté l'une de ces approches, le compilateur Compose marque à présent
Composable HighlightedSnacks
en tant que skippable
et 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
)
Lors de la recomposition, Compose peut désormais ignorer HighlightedSnacks
si aucune de ses
ont changé.
Fichier de configuration de la stabilité
À partir de Compose Compiler 1.5.5, un fichier de configuration des classes
comme stable peut être fournie au moment de la compilation. Cela permet d'envisager
les classes que vous ne contrôlez pas, telles que les classes de bibliothèque standards ;
comme LocalDateTime
, comme étant stable.
Le fichier de configuration est un fichier au format texte brut contenant une classe par ligne. Commentaires les caractères génériques simples et doubles sont acceptés. Voici un exemple de configuration:
// 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<*,_>
Pour activer cette fonctionnalité, transmettez le chemin d'accès du fichier de configuration à Compose les options du compilateur.
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"
)
}
Comme le compilateur Compose s'exécute sur chaque module de votre projet séparément, vous pouvez fournir différentes configurations pour différents modules si nécessaire. Vous pouvez aussi en avoir un au niveau racine de votre projet et de transmettre ce chemin d'accès de ce module.
Plusieurs modules
Un autre problème courant concerne l'architecture multimodule. Compilateur Compose ne peut déterminer si une classe est stable que si tous les types non primitifs qui auxquelles il fait référence sont soit explicitement marquées comme stables, soit dans un module qui a été également créé avec le compilateur Compose.
Si votre couche de données se trouve dans un module distinct de votre couche d'UI, qui correspond au l'approche recommandée, il peut s'agir d'un problème que vous rencontrez.
Solution
Pour résoudre ce problème, vous pouvez adopter l'une des approches suivantes:
- Ajouter les classes à votre fichier de configuration de compilateur.
- Activez le compilateur Compose sur vos modules de couche de données ou ajoutez des tags à vos classes
avec
@Stable
ou@Immutable
, le cas échéant.- Cela implique d'ajouter une dépendance Compose à votre couche de données. Toutefois,
il s'agit simplement de la dépendance pour l'environnement d'exécution Compose, et non pour
Compose-UI
- Cela implique d'ajouter une dépendance Compose à votre couche de données. Toutefois,
il s'agit simplement de la dépendance pour l'environnement d'exécution Compose, et non pour
- Dans votre module d'UI, encapsulez vos classes de couche de données dans un wrapper spécifique à l'UI. classes.
Le même problème se produit lors de l'utilisation de bibliothèques externes si celles-ci n'utilisent pas Compilateur Compose.
Tous les composables ne doivent pas être désactivables
Lorsque vous essayez de résoudre les problèmes de stabilité, vous ne devez pas essayer de composable désactivable. Toute tentative d'optimisation peut entraîner une optimisation prématurée. qui introduit plus de problèmes qu’il n’en résout.
Dans de nombreuses situations, le choix d'une annonce désactivable ne présente aucun avantage réel. et peut rendre le code difficile à gérer. Exemple :
- Un composable qui n'est pas souvent recomposé, voire pas du tout.
- Un composable qui, en soi, appelle simplement des composables désactivables.
- Un composable avec un grand nombre de paramètres avec cher est égal à mises en œuvre. Dans ce cas, le coût de la vérification si un paramètre a pourraient l'emporter sur le coût d'une recomposition bon marché.
Lorsqu'un composable est désactivable, cela ajoute une légère surcharge qui n'en vaut peut-être pas la peine. Vous pouvez même annoter votre composable de sorte qu'il ne soit pas redémarrable dans les cas où vous déterminez que le fait d'être redémarré est plus coûteux que ça ne vaut le coup.