Gérer les modifications de configuration

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

  • Taille d'affichage de l'application
  • Densité d'écran (mise à l'échelle de l'affichage)
  • Orientation de l'écran
  • Taille et épaisseur de la police
  • Paramètres régionaux
  • Thème sombre et thème clair
  • Disponibilité du clavier

La plupart de ces modifications de configuration sont dues à une interaction de l'utilisateur. Par exemple, faire pivoter ou plier l'appareil modifie la quantité d'espace disponible sur l'écran pour votre application. Se connecter à des écrans externes ou déplacer une application entre des écrans de densités de pixels différentes modifie la densité de l'écran et la taille d'affichage. De même, la modification des paramètres de l'appareil, tels que la mise à l'échelle de l'affichage, 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'interface utilisateur de votre application pour que la plate-forme Android dispose d'un mécanisme spécialement conçu pour les modifier. Ce mécanisme est la recréation de Activity.

Recréation d'activité

Le système recrée une Activity lorsqu'un changement 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, et cette nouvelle instance Activity est initialisée avec la nouvelle configuration mise à jour. Cela signifie également que le système recrée l'UI avec la nouvelle configuration.

En règle générale, Activity sert d'hôte pour les composables. Lorsque l'Activity est recréée, 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 la rechargeant automatiquement avec d'autres ressources 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 Activity est créé, le composable Text lit la configuration actuelle (comme 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. Comme 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é en tant que champs dans Activity.

Pour conserver l'état de votre UI lors des 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'interface utilisateur est mise à 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 frustrant pour lui de revenir à un formulaire vide 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
  • Activation du mode multifenêtre
  • Redimensionnement de l'application en mode multifenêtre ou dans une fenêtre de format libre
  • Plier un appareil pliable doté de plusieurs écrans
  • Modification de la taille d'affichage ou de la mise à l'échelle de l'affichage dans les paramètres système
  • Déplacement de l'application entre des écrans de densités différentes (par exemple, des écrans externes connectés ou les écrans d'un appareil pliable)
  • Changer le thème du système (par exemple, passer du thème sombre au thème 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 d'accueil

Il existe plusieurs approches pour conserver l'état pertinent lors de la recréation de Activity. Le choix de l'option 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 pour un état qui dépend de la saisie de l'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 de chacune de ces options et sur les cas d'utilisation appropriés, consultez Enregistrer les états de l'interface utilisateur.

Restreindre la recréation d'activité

Vous pouvez empêcher la recréation automatique d'une activité pour certaines modifications de configuration. Dans les applications modernes qui n'utilisent que 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 force 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'en empêche. Seul l'objet Configuration est mis à jour, et Compose recompose votre UI avec les nouvelles valeurs.

La gestion des modifications de configuration directement dans Compose présente plusieurs avantages :

  • Amélioration des performances : 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 temporaire de l'UI lors d'un événement tel que la rotation de l'écran. Notez que vous devez toujours gérer la conservation de l'état pour l'arrêt du 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'UI complète. 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 repose sur un redémarrage complet pour actualiser 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 modifications 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 changements de configuration

Jetpack Compose permet à votre application de réagir plus facilement aux modifications de configuration. Toutefois, même si vous désactivez la recréation de Activity pour toutes les modifications de configuration lorsque 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'interface utilisateur 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 compositions locales, 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 de recréer Activity lorsque les paramètres régionaux changent, l'Activity qui héberge le 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 configuration : concepts clés et bonnes pratiques

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

  • Configurations : les configurations de l'appareil définissent la façon dont l'UI s'affiche pour l'utilisateur, par exemple la taille d'affichage de l'application, la densité de l'écran, les paramètres régionaux 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 de l'utilisateur. 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 d'Activity : les modifications de configuration entraînent la recréation d'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 par le système et la création d'une nouvelle instance à la place. L'ancienne instance est désormais obsolète. Évitez de conserver des références à des objets limités au 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 d'associer l'état à l'activité, utilisez les API recommandées pour préserver l'état de l'application et de l'utilisateur, comme décrit dans Enregistrer les états de l'interface utilisateur.
  • 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éponse à la nouvelle configuration.

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

  • Préparez-vous à des changements de configuration fréquents : ne partez pas du principe que les changements de configuration sont rares ou ne se produisent jamais, quels que soient le niveau d'API, le facteur de forme ou le kit d'outils d'interface utilisateur. Lorsqu'un utilisateur modifie la configuration, il s'attend à ce que les applications se mettent à jour et continuent de fonctionner correctement avec la nouvelle configuration.
  • Conserver l'état : ne perdez pas l'état de l'utilisateur lorsque Activity est recréé. Conservez l'état comme décrit dans Enregistrer les états de l'interface utilisateur à l'aide d'API telles que ViewModel et rememberSaveable.
  • Évitez de désactiver la recréation de comme solution rapide : ne désactivez pas la recréation de Activity pour éviter la perte d'état. Si vous désactivez la recréation d'activité, vous devez vous engager à gérer la modification. Vous pouvez toujours perdre l'état en raison de la recréation d'Activity à partir d'autres modifications de configuration, de l'arrêt du processus ou de la fermeture de l'application. Il est impossible de désactiver entièrement la recréation d'Activity. Conservez l'état comme décrit dans Enregistrer les états de l'UI.
  • N'évitez pas les modifications de configuration : n'imposez pas de restrictions sur l'orientation, le format ou la redimensionnabilité pour éviter les modifications de configuration et la recréation d'Activity. Cela a un impact négatif sur les utilisateurs qui souhaitent utiliser votre application de la manière qu'ils préfèrent.

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 probables 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 généralement deux types de changements de taille : significatifs et insignifiants. Un changement de taille significatif est un changement dans lequel un ensemble différent de ressources alternatives s'applique à la nouvelle configuration en raison d'une différence de taille d'écran, telle que la largeur, la hauteur ou la plus petite largeur. Ces ressources incluent celles que l'application définit elle-même et celles 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 basées sur la taille, le système ne recrée pas l'Activity. En revanche, il reçoit un appel à Activity.onConfigurationChanged. Tous les composables lisant LocalConfiguration.current se recomposent automatiquement pour refléter la nouvelle taille.

La recréation de 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

Contenu des vues