Gérer les modifications de configuration

Certaines configurations d'appareil peuvent changer pendant l'exécution de l'application. Il s'agit notamment : sans s'y limiter:

  • Taille d'affichage de l'application
  • Orientation de l'écran
  • Taille et épaisseur de la police
  • Langue
  • Comparaison entre le mode sombre et le mode clair
  • Disponibilité du clavier

La plupart de ces changements de configuration sont dus à une interaction de l'utilisateur. Pour Par exemple, la rotation ou le pliage de l'appareil modifie l'espace à l'écran disponibles pour votre application. De même, la modification des paramètres de l'appareil tels que la taille de la police, langue ou thème préféré modifie leurs valeurs respectives dans le objet Configuration.

Ces paramètres nécessitent généralement des modifications suffisamment importantes de l'interface utilisateur de votre application que la plate-forme Android dispose d'un mécanisme sur mesure en cas de changement. Ce mécanisme est la recréation d'Activity.

Recréation d'activité

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

Le comportement de recréation aide votre application à s'adapter à de nouvelles configurations en Recharger automatiquement votre application avec d'autres ressources correspondant la nouvelle configuration de l'appareil.

Exemple d'activité de loisirs

Prenons l'exemple d'un TextView qui affiche un titre statique avec android:text="@string/title", tel que défini dans un fichier XML de mise en page. Lorsque la vue le texte est défini exactement une fois, en fonction de la langue actuelle. Si le les modifications de langue, le système recrée l'activité. Par conséquent, le système recrée également la vue et l'initialise sur la valeur correcte en fonction du nouveau langue.

La recréation efface également tout état conservé en tant que champs dans Activity ou dans l'un des objets Fragment, View ou d'autres objets qu'il contient. Ce est dû au fait que la recréation d'Activity crée une instance entièrement nouvelle de Activity. et l'UI. De plus, l'ancienne valeur de Activity n'est plus visible ni valide. les références restantes à elle ou aux objets qu'elle contient sont obsolètes. Ils peuvent entraîner les bugs, les fuites de mémoire et les plantages.

Attentes des utilisateurs

L'utilisateur d'une application s'attend à ce que l'état soit préservé. Si un utilisateur remplit un formulaire et ouvre une autre application en mode multifenêtre pour référencer des informations, nuit à l'expérience utilisateur s'il retourne dans un formulaire effacé ou ailleurs dans l’application. En tant que développeur, vous devez fournir une expérience utilisateur cohérente en modifiant la configuration et en recréant des activités.

Pour vérifier si l'état est conservé dans votre application, vous pouvez effectuer qui entraînent des modifications de configuration lorsque l'application est exécutée au premier plan lorsqu'elle est exécutée 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 avec plusieurs écrans
  • Modifier le thème du système (mode sombre ou mode clair, par exemple)
  • 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 trois approches principales pour préserver un état pertinent à travers Recréation de Activity. Le choix à utiliser dépend du type d'état que vous souhaitez conserver:

  • La persistance locale permet de gérer l'arrêt du processus pour les données complexes ou volumineuses. Le stockage local persistant inclut des bases de données ou des DataStore.
  • Les objets conservés, tels que les instances ViewModel, pour gérer l'état de l'UI dans mémoire lorsque l'utilisateur utilise activement l'application.
  • État d'instance enregistré pour gérer un arrêt de processus déclenché par le système et conserver un état temporaire qui dépend de l'entrée utilisateur ou de la navigation.

Pour en savoir plus sur les API pour chacun d'eux, Si vous les utilisez, consultez Enregistrer les états de l'interface utilisateur.

Restreindre la recréation de l'activité

Vous pouvez empêcher la recréation automatique de l'activité pour certaines modifications de configuration. La recréation d'Activity entraîne la recréation de l'intégralité de l'UI et de tous les objets dérivés. à partir de Activity. Vous avez peut-être de bonnes raisons d'éviter cela. Pour Par exemple, il est possible que votre application n'ait pas besoin de mettre à jour les ressources au cours d'une modification de la configuration, ou les performances peuvent être limitées. Dans ce cas, vous pouvez déclarer que votre activité gère elle-même le changement de configuration. empêcher le système de redémarrer votre activité.

Pour désactiver la recréation d'activité pour des modifications de configuration particulières, procédez comme suit : ajoutez le type de configuration à android:configChanges dans Entrée <activity> dans votre fichier AndroidManifest.xml. Les valeurs possibles apparaissent dans les Documentation sur l'attribut android:configChanges.

Le code manifeste suivant désactive la recréation d'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">

Certaines modifications de configuration entraînent toujours le redémarrage de l'activité. Vous ne pouvez pas désactiver de l'IA générative. Par exemple, vous ne pouvez pas désactiver le changement des couleurs dynamiques. introduit dans Android 12L (niveau d'API 32).

Réagir aux modifications de configuration dans le système de vues

Dans le système View, lorsqu'une modification de configuration se produit pour laquelle vous avez la recréation d'Activity est désactivée, l'activité reçoit un appel vers Activity.onConfigurationChanged() Toutes les vues associées reçoivent également une à View.onConfigurationChanged(). Pour les modifications de configuration, n'ont pas été ajoutés à android:configChanges, le système recrée l'activité comme d'habitude.

La méthode de rappel onConfigurationChanged() reçoit une Objet Configuration qui spécifie la nouvelle configuration de l'appareil. Lue les champs de l'objet Configuration pour déterminer configuration. Pour apporter les modifications suivantes, mettez à jour les ressources que vous utilisez dans votre interface. Lorsque le système appelle cette méthode, l'état L'objet Resources est mis à jour pour renvoyer des ressources basées sur les nouvelles configuration. Cela vous permet de réinitialiser des éléments de votre interface utilisateur sans passer par le système redémarrer votre activité.

Par exemple, les vérifications d'implémentation onConfigurationChanged() suivantes si un clavier est disponible:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
    } else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
    }
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
    } else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
    }
}

Si vous n'avez pas besoin de mettre à jour votre application en fonction de ces vous ne pouvez pas implémenter onConfigurationChanged(). Dans ce toutes les ressources utilisées avant le changement de configuration le sont toujours, et vous avez seulement évité le redémarrage de votre activité. Par exemple, une application TV peut ne pas réagir lorsqu'un clavier Bluetooth est connecté ou déconnecté.

Conserver l'état

Lorsque vous utilisez cette technique, vous devez conserver l'état du cycle de vie d'une activité. Cela est dû aux raisons suivantes:

  • Modifications inévitables:les modifications de configuration que vous ne pouvez pas empêcher peuvent redémarrer votre application.
  • Arrêt du processus:votre application doit pouvoir gérer les opérations déclenchées par le système. l'arrêt du processus. Si l'utilisateur quitte votre application et que celle-ci accède au en arrière-plan, le système risque de détruire l'application.

Réagir aux modifications de configuration dans Jetpack Compose

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ù il se trouve votre application doit gérer correctement les modifications de configuration.

L'objet Configuration est disponible dans la hiérarchie de l'UI Compose avec la composition LocalConfiguration locale. Chaque fois qu'elle change, Les fonctions composables lues à partir de LocalConfiguration.current sont recomposées. Pour des informations sur le fonctionnement local de la composition, consultez la section À l'échelle locale avec CompositionLocal.

Exemple

Dans l'exemple suivant, un composable affiche une date dans un format spécifique. Le composable réagit aux modifications de la 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 d'Activity lorsque les paramètres régionaux changent, le Activity hébergeant le Le code Compose doit désactiver les modifications de configuration des paramètres régionaux. Pour ce faire, vous devez définissez android:configChanges sur locale|layoutDirection.

Modifications de configuration: concepts clés et bonnes pratiques

Ce sont les concepts clés que vous devez connaître lorsque vous travaillez sur la configuration modifications:

  • Configurations:les configurations d'appareil définissent la façon dont l'interface utilisateur s'affiche pour l'utilisateur, comme la taille d'affichage de l'application, les paramètres régionaux ou le thème du système.
  • Modifications de la configuration:les configurations sont modifiées via une interaction de l'utilisateur. Pour 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'y a aucun moyen d'empêcher les modifications de configuration.
  • Recréation de Activity:les modifications de la 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 nouvelle configuration.
  • Destruction de Activity:la recréation d'Activity amène le système à détruire le l'ancienne instance Activity et en créer une nouvelle à la place. L'ancienne instance est est désormais obsolète. Toutes les références restantes à celui-ci entraînent des fuites de mémoire, les bugs ou les plantages.
  • State (État) : l'état de l'ancienne instance Activity n'est pas présent dans la nouvelle Activity, car il s'agit de deux instances d'objet différentes. Préserver l'état de l'application et de l'utilisateur, comme décrit dans la section Enregistrer les états de l'interface utilisateur ;
  • Désactiver:désactiver la recréation de l'activité pour un type de configuration le changement est une optimisation potentielle. Cela nécessite que votre application se met à 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 de configuration fréquentes:ne partez pas du principe que les modifications sont rares ou ne se produisent jamais, quels que soient le niveau d'API, le facteur de forme ou le kit d'interface utilisateur. Lorsqu'un utilisateur modifie la configuration, il s'attend à ce que les applications soient mises à jour et de continuer à fonctionner correctement avec la nouvelle configuration.
  • Préserver l'état:ne perdez pas l'état de l'utilisateur lors de la recréation d'Activity. se produit. Conservez l'état comme décrit dans la section Enregistrer les états de l'interface utilisateur.
  • Solution rapide:évitez de désactiver la recréation d'Activity. pour éviter de perdre un état. La désactivation de la recréation d'activité nécessite de tenir la promesse de gestion du changement, et vous risquez de perdre en raison de la recréation d'Activity à partir d'autres modifications de configuration, processus le décès ou la fermeture de l'application. Il est impossible de désactiver complètement Activity la recréation d'un objet. Conservez l'état comme décrit dans la section Enregistrer les états de l'interface utilisateur.
  • N'évitez pas les modifications de configuration:ne limitez pas l'orientation, le format ou le redimensionnement pour éviter les modifications de configuration Recréation de Activity. Cela a un impact négatif sur les utilisateurs qui souhaitent utiliser votre application dans leur méthode préférée.

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

Des modifications de configuration basées sur la taille peuvent se produire à tout moment et sont plus susceptibles Lorsque votre application s'exécute sur un appareil à grand écran sur lequel les utilisateurs peuvent saisir mode multifenêtre. Ils s'attendent à ce que votre application fonctionne bien dans ce contexte. environnement.

Il existe deux types généraux de changements de taille: importants et sans importance. Un changement de taille important est un changement les autres ressources s'appliquent à la nouvelle configuration, en raison d'une différence taille d'écran, comme la largeur, la hauteur ou la plus petite largeur. Ces ressources incluent : ceux que l'application définit elle-même et ceux de ses bibliothèques.

Restreindre la recréation d'activités pour les modifications de configuration basées sur la taille

Lorsque vous désactivez la recréation d'Activity pour les modifications de configuration basées sur la taille, ne recrée pas l'Activity. Au lieu de cela, il reçoit un appel Activity.onConfigurationChanged() Toutes les vues associées reçoivent un appel à View.onConfigurationChanged()

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

Autoriser la recréation d'activités pour les modifications de configuration basées sur la taille

Sur Android 7.0 (niveau d'API 24) ou version ultérieure, la recréation de Activity se produit uniquement pour les applications basées sur la taille si le changement de taille est important. Lorsque le système ne Si vous recréez un Activity en raison d'une taille insuffisante, le système peut appeler Activity.onConfigurationChanged() et View.onConfigurationChanged() à la place.

Voici quelques mises en garde à prendre en compte concernant Activity et View. des rappels lorsque Activity n'est pas recréé:

  • Sur Android 11 (niveau d'API 30) à Android 13 (niveau d'API 33), Activity.onConfigurationChanged() n'est pas appelé.
  • Il se peut que View.onConfigurationChanged() ne se trouve pas en raison d'un problème connu appelé dans certains cas sur Android 12L (niveau d'API 32) et les premières versions de Android 13 (niveau d'API 33). Pour en savoir plus, consultez ce problème public. Ce problème a depuis été résolu dans les versions ultérieures d'Android 13 et d'Android 14.

Pour le code qui dépend de l'écoute d'une configuration basée sur la taille nous vous recommandons d'utiliser un utilitaire View avec une valeur View.onConfigurationChanged() au lieu de s'appuyer sur la recréation ou la récupération de Activity Activity.onConfigurationChanged()