Gérer les modifications de configuration

Certaines configurations d'appareil peuvent changer pendant l'exécution de l'application. Voici quelques exemples :

  • Taille d'affichage de l'application
  • Orientation de l'écran
  • Taille et épaisseur de la police
  • Paramètres régionaux
  • Mode sombre ou mode clair
  • Disponibilité du clavier

La plupart de ces modifications de configuration se produisent en raison d'une interaction de l'utilisateur. Par exemple, la rotation ou le pliage de l'appareil modifient la quantité d'espace disponible sur l'écran pour votre application. De même, la modification des paramètres de l'appareil, comme la taille de la police, la langue ou le thème préféré, modifie leurs valeurs respectives dans l'objet Configuration.

Ces paramètres nécessitent généralement des modifications suffisamment importantes de l'UI de votre application pour que la plate-forme Android dispose d'un mécanisme spécialement conçu pour leur modification. Ce mécanisme s'appelle la recréation Activity.

Recréation d'activité

Le système recrée une Activity lorsqu'une modification de configuration se produit. Pour ce faire, le système appelle onDestroy et détruit l'instance Activity existante. Il crée ensuite une instance à l'aide de onCreate. Cette nouvelle instance Activity est initialisée avec la nouvelle configuration mise à jour. Cela signifie également que le système recrée l'interface utilisateur avec la nouvelle configuration.

En général, Activity sert d'hôte pour les composables. Lorsque Activity est recréé, Compose recrée également votre UI à l'aide des nouvelles valeurs de configuration.

Le comportement de recréation aide votre application à s'adapter aux nouvelles configurations en rechargeant automatiquement votre application avec des ressources alternatives correspondant à la nouvelle configuration de l'appareil.

Exemple de loisirs

Prenons l'exemple d'un composable qui affiche un titre statique à l'aide d'une ressource de chaîne :

// In the res/values/strings.xml file
// <string name="compose">Jetpack Compose</string>

// In your Compose code
Text(
    text = stringResource(R.string.compose)
)

Lorsque le Activity est créé, le composable Text lit la configuration actuelle (telle que la langue) et résout la ressource de chaîne appropriée.

Si la langue change, le système recrée l'activité. Dans ce cas, Compose recrée l'UI. Étant donné que stringResource lit la configuration actuelle, le titre est automatiquement mis à jour avec la valeur localisée correcte.

La recréation efface également tout état conservé sous forme de champs dans Activity.

Pour conserver l'état de votre UI en cas de modifications de configuration, utilisez les modèles de gestion d'état recommandés. Utilisez ViewModel pour les données et la logique métier, et rememberSaveable pour l'état au niveau de l'UI. Grâce à ces mécanismes, votre état survit à la recréation de Activity tandis que l'UI se met à jour pour refléter la nouvelle configuration.

Pour en savoir plus sur l'enregistrement de l'état dans Compose, consultez Enregistrer l'état de l'UI dans Compose.

Attentes des utilisateurs

L'utilisateur d'une application s'attend à ce que l'état soit conservé. Si un utilisateur remplit un formulaire et ouvre une autre application en mode multifenêtre pour consulter des informations, il est désagréable pour lui de revenir à un formulaire effacé ou à un autre endroit de l'application. En tant que développeur, vous devez fournir une expérience utilisateur cohérente lors des modifications de configuration et de la recréation d'activités.

Pour vérifier si l'état est conservé dans votre application, vous pouvez effectuer des actions qui entraînent des modifications de configuration à la fois lorsque l'application est au premier plan et lorsqu'elle est en arrière-plan. Ces actions incluent :

  • Faire pivoter l'appareil
  • Activer le mode multifenêtre
  • Redimensionner l'application en mode multifenêtre ou dans une fenêtre de format libre
  • Plier un appareil pliable à plusieurs écrans
  • Changer le thème du système (par exemple, passer du mode sombre au mode clair)
  • Modifier la taille de la police
  • Modifier la langue du système ou de l'application
  • Connecter ou déconnecter un clavier physique
  • Connecter ou déconnecter une station de recharge

Plusieurs approches sont possibles pour préserver l'état pertinent lors de la recréation de Activity. Le choix dépend du type d'état que vous souhaitez conserver :

  • Persistance locale pour gérer l'arrêt du processus pour des données complexes ou volumineuses. Le stockage local persistant inclut les bases de données ou DataStore.
  • Objets conservés tels que les instances ViewModel pour gérer l'état lié à l'UI en mémoire lorsque l'utilisateur utilise activement l'application.
  • rememberSaveable pour conserver l'état transitoire de l'UI lors des modifications de configuration et de l'arrêt d'un processus initié par le système. Cela convient à l'état qui dépend de l'entrée utilisateur, de la position de défilement ou de la navigation, mais qui n'appartient pas à un ViewModel.

Pour en savoir plus sur les API pour chacun de ces cas et sur le moment où il convient d'utiliser chacune d'elles, consultez Enregistrer les états de l'UI.

Restreindre la recréation d'activité

Vous pouvez empêcher la recréation automatique de l'activité pour certaines modifications de configuration. Dans les applications modernes utilisant uniquement Compose, votre UI est recomposée dans les deux cas, mais il est recommandé de gérer directement le changement de configuration.

Par défaut, une modification de configuration oblige le système à détruire et à recréer l'activité, y compris l'UI et tous les objets dérivés de l'activité. Si vous déclarez que votre activité gère elle-même le changement de configuration, le système l'empêche. Seul l'objet Configuration est mis à jour, et Compose recompose votre UI avec les nouvelles valeurs.

Gérer les modifications de configuration directement dans Compose présente plusieurs avantages :

  • Performances améliorées : la recomposition de l'UI est moins coûteuse qu'un cycle complet de recréation d'activité, en particulier pour les modifications mineures.
  • Animations fluides : éviter le redémarrage d'une activité vous permet d'exécuter des animations continues lors des modifications de configuration, comme des transitions de mise en page fluides lors de la rotation de l'appareil.
  • Préservation de l'état : la conservation de l'instance d'activité réduit le risque de perte d'état d'interface utilisateur temporaire lors d'un événement tel que la rotation de l'écran. Notez que vous devez toujours gérer la conservation de l'état en cas d'arrêt de processus initié par le système.

Pour désactiver la recréation d'activité pour des modifications de configuration spécifiques, ajoutez le type de configuration à android:configChanges dans l'entrée <activity> de votre fichier AndroidManifest.xml. Les valeurs possibles figurent dans la documentation de l'attribut android:configChanges.

Le code de fichier manifeste suivant désactive la recréation de Activity pour MyActivity lorsque l'orientation de l'écran et la disponibilité du clavier changent :

<activity
    android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
    android:label="@string/app_name">

Android 17

À partir d'Android 17 (niveau d'API 37), le système ne redémarre plus les activités par défaut pour plusieurs modifications de configuration qui ne nécessitent généralement pas de recréer l'intégralité de l'UI. Au lieu de cela, les activités restent actives et reçoivent des mises à jour via le rappel onConfigurationChanged(). Voici les modifications de configuration spécifiques :

Si votre application s'appuie sur un redémarrage complet pour recharger les ressources de ces modifications, vous devez désormais activer explicitement l'ancien comportement à l'aide de l'attribut android:recreateOnConfigChanges dans le fichier manifeste. Cet attribut vous permet de spécifier les changements de configuration qui doivent déclencher un cycle complet d'arrêt, de destruction et de recréation de l'activité. Par exemple :

<activity
    android:name=".MyActivity"
    android:recreateOnConfigChanges="keyboard|keyboardHidden|navigation|colorMode|touchscreen|...">
    ...
</activity>

Réagir aux modifications de configuration

Jetpack Compose permet à votre application de réagir plus facilement aux modifications de configuration. Toutefois, si vous désactivez la recréation d'Activity pour toutes les modifications de configuration où cela est possible, votre application doit toujours gérer correctement les modifications de configuration.

L'objet Configuration est disponible dans la hiérarchie de l'UI Compose avec la composition locale LocalConfiguration. Chaque fois qu'il change, les fonctions composables qui lisent LocalConfiguration.current sont recomposées. Pour en savoir plus sur le fonctionnement des CompositionLocals, consultez Données à champ d'application local avec CompositionLocal.

Exemple

Dans l'exemple suivant, un composable affiche une date dans un format spécifique. Le composable réagit aux modifications de configuration des paramètres régionaux du système en appelant ConfigurationCompat.getLocales avec LocalConfiguration.current.

@Composable
fun DateText(year: Int, dayOfYear: Int) {
    val dateTimeFormatter = DateTimeFormatter.ofPattern(
        "MMM dd",
        ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
    )
    Text(
        dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
    )
}

Pour éviter la recréation de Activity lorsque les paramètres régionaux changent, l'hôte Activity du code Compose doit désactiver les modifications de configuration des paramètres régionaux. Pour ce faire, définissez android:configChanges sur locale|layoutDirection.

Modifications de la configuration : concepts clés et bonnes pratiques

Voici les concepts clés à connaître lorsque vous modifiez la configuration :

  • Configurations : les configurations d'appareil définissent la façon dont l'UI s'affiche pour l'utilisateur, par exemple la taille d'affichage de l'application, la langue ou le thème du système. Dans Compose, vous pouvez accéder aux valeurs de configuration à l'aide de LocalConfiguration.
  • Modifications de la configuration : les configurations changent en fonction des interactions des utilisateurs. Par exemple, l'utilisateur peut modifier les paramètres de l'appareil ou la façon dont il interagit physiquement avec l'appareil. Il n'existe aucun moyen d'empêcher les modifications de configuration.
  • Recréation de Activity : les modifications de configuration entraînent la recréation de Activity par défaut. Il s'agit d'un mécanisme intégré permettant de réinitialiser l'état de l'application pour la nouvelle configuration.
  • Destruction de Activity : la recréation de Activity entraîne la destruction de l'ancienne instance Activity et la création d'une nouvelle à sa place. L'ancienne instance est désormais obsolète. Évitez de conserver des références à des objets à portée de cycle de vie au-delà de leur portée prévue.
  • État : l'état de l'ancienne instance Activity n'est pas présent dans la nouvelle instance Activity, car il s'agit de deux instances d'objet différentes. Au lieu de lier l'état à l'activité, utilisez les API recommandées pour conserver l'état de l'application et de l'utilisateur, comme décrit dans Enregistrer les états de l'UI.
  • Désactivation : pour désactiver la recréation d'activité pour un type de modification de configuration, votre application doit se mettre à jour correctement en réaction à la nouvelle configuration.

Pour offrir une expérience utilisateur de qualité, suivez les bonnes pratiques suivantes :

  • Préparez-vous à des modifications fréquentes de la configuration : ne partez pas du principe que les modifications de la configuration sont rares ou n'arrivent jamais, quel que soit le niveau d'API, le facteur de forme ou la boîte à outils d'UI. Lorsqu'un utilisateur modifie une configuration, il s'attend à ce que les applications se mettent à jour et continuent de fonctionner correctement avec la nouvelle configuration.
  • Conservez l'état : ne perdez pas l'état de l'utilisateur lorsque la recréation Activity se produit. Conservez l'état comme décrit dans Enregistrer les états de l'UI à l'aide d'API telles que ViewModel et rememberSaveable.
  • Évitez de désactiver la recréation comme solution rapide : ne désactivez pas la recréation de Activity comme raccourci pour éviter la perte d'état. Si vous choisissez de ne pas recréer l'activité, vous devez tenir votre engagement de gérer le changement. Vous pouvez toujours perdre l'état en raison de la recréation de Activity suite à d'autres modifications de configuration, à l'arrêt du processus ou à la fermeture de l'application. Il est impossible de désactiver complètement la recréation de Activity. Conservez l'état comme décrit dans Enregistrer les états de l'UI.
  • Ne pas éviter les modifications de configuration : ne pas imposer de restrictions sur l'orientation, le format ou la redimensionnabilité pour éviter les modifications de configuration et la recréation d'Activity. Cela nuit aux utilisateurs qui souhaitent utiliser votre application de la manière qui leur convient.

Gérer les modifications de configuration basées sur la taille

Les changements de configuration basés sur la taille peuvent se produire à tout moment et sont plus susceptibles de se produire lorsque votre application s'exécute sur un appareil à grand écran sur lequel les utilisateurs peuvent passer en mode multifenêtre. Ils s'attendent à ce que votre application fonctionne correctement dans cet environnement.

Il existe deux types généraux de modifications de taille : importantes et non importantes. Une modification de taille importante se produit lorsqu'un ensemble différent de ressources alternatives s'applique à la nouvelle configuration en raison d'une différence de taille d'écran, comme la largeur, la hauteur ou la plus petite largeur. Ces ressources incluent celles que l'application définit elle-même et celles de l'une de ses bibliothèques.

Limiter la recréation d'activité pour les modifications de configuration en fonction de la taille

Lorsque vous désactivez la recréation d'Activity pour les modifications de configuration en fonction de la taille, le système ne recrée pas l'Activity. En revanche, il reçoit un appel à Activity.onConfigurationChanged. Tous les composables qui lisent LocalConfiguration.current se recomposent automatiquement pour refléter la nouvelle taille.

La recréation Activity est désactivée pour les modifications de configuration basées sur la taille lorsque vous avez android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" dans votre fichier manifeste.

Ressources supplémentaires

Pour en savoir plus sur la gestion des modifications de configuration, consultez les ressources supplémentaires suivantes :

Documentation

Afficher le contenu