Utilisez les valeurs "Preference" enregistrées. Fait partie d'Android Jetpack.

Ce document explique comment stocker et utiliser les valeurs Preference enregistrées par la bibliothèque des préférences.

Préférence de stockage des données

Cette section décrit comment un Preference peut conserver des données.

SharedPreferences

Par défaut, un Preference utilise SharedPreferences pour enregistrer les valeurs. L'API SharedPreferences permet de lire et d'écrire des paires clé/valeur simples à partir d'un fichier enregistré dans plusieurs sessions d'application. La bibliothèque des préférences utilise une instance SharedPreferences privée afin que seule votre application puisse y accéder.

Par exemple, supposons que le SwitchPreferenceCompat suivant soit employé:

<SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

Lorsqu'un utilisateur bascule ce bouton sur l'état "activé", le fichier SharedPreferences est mis à jour avec une paire clé-valeur "notifications" : "true". La clé utilisée est identique à celle définie pour Preference.

Pour en savoir plus sur l'API SharedPreferences, consultez la section Enregistrer les données clé-valeur.

Pour en savoir plus sur les différentes façons de stocker des données sur Android, consultez la section Présentation du stockage de données et de fichiers.

PreferenceDataStore

Bien que la bibliothèque des préférences conserve les données avec SharedPreferences par défaut, SharedPreferences ne constitue pas toujours une solution idéale. Par exemple, si votre application nécessite qu'un utilisateur se connecte, vous pouvez conserver les paramètres de l'application dans le cloud afin qu'ils soient répercutés sur d'autres appareils et plates-formes. De même, si votre application dispose d'options de configuration spécifiques à l'appareil, chaque utilisateur de l'appareil dispose de paramètres distincts, ce qui fait de SharedPreferences une solution moins idéale.

Un PreferenceDataStore vous permet d'utiliser un backend de stockage personnalisé pour conserver les valeurs Preference. Pour en savoir plus, consultez la section Utiliser un datastore personnalisé.

Lire les valeurs de préférences de lecture

Pour récupérer l'objet SharedPreferences utilisé, appelez PreferenceManager.getDefaultSharedPreferences(). Bien que cette méthode fonctionne depuis n'importe où dans votre application, nous vous recommandons de la diviser en couches. Pour en savoir plus, consultez la section Couche de données.

Par exemple, pour un EditTextPreference avec une clé de "signature", comme suit:

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

Vous pouvez récupérer la valeur enregistrée pour ce Preference de manière globale, comme suit:

Kotlin

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */)
val name = sharedPreferences.getString("signature", "")

Java

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString("signature", "");

Écouter les modifications apportées aux valeurs de préférences

Pour écouter les modifications apportées aux valeurs Preference, vous avez le choix entre deux interfaces:

Le tableau suivant montre les différences entre les deux interfaces:

OnPreferenceChangeListener OnSharedPreferenceChangeListener
Défini sur un seul Preference. S'applique à tous les objets Preference.
Appelée lorsqu'une valeur Preference est sur le point de modifier sa valeur enregistrée, même si la valeur en attente est identique à la valeur enregistrée. Appelé uniquement lorsque la valeur enregistrée pour un Preference change.
Appel uniquement via la bibliothèque Preference. Une partie de l'application peut modifier la valeur enregistrée. Appelée chaque fois que la valeur enregistrée change, même si elle provient d'une partie distincte de l'application.
Appelée avant l'enregistrement de la valeur en attente. Appelée après l'enregistrement de la valeur.
Appelée lors de l'utilisation de SharedPreferences ou d'un PreferenceDataStore. Appelé uniquement lors de l'utilisation de SharedPreferences.

Implémenter OnPreferenceChangeListener

L'implémentation d'un OnPreferenceChangeListener vous permet d'écouter une modification en attente de la valeur d'un Preference. Vous pouvez ensuite vérifier si la modification a lieu. Par exemple, le code suivant montre comment écouter une modification de la valeur d'un élément EditTextPreference avec une clé de "name":

Kotlin

override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
    Log.e("preference", "Pending Preference value is: $newValue")
    return true
}

Java

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.e("preference", "Pending Preference value is: " + newValue);
    return true;
}

Vous devez ensuite définir cet écouteur directement avec setOnPreferenceChangeListener(), comme suit:

Kotlin

preference.onPreferenceChangeListener = ...

Java

preference.setOnPreferenceChangeListener(...);

Implémenter OnSharedPreferenceChangeListener

Lorsque vous conservez des valeurs Preference à l'aide de SharedPreferences, vous pouvez également utiliser un SharedPreferences.OnSharedPreferenceChangeListener pour écouter les modifications. Cela vous permet d'écouter quand les valeurs enregistrées par votre Preference sont modifiées, par exemple lors de la synchronisation des paramètres avec un serveur. L'exemple suivant montre comment écouter une modification de la valeur d'un élément EditTextPreference avec une clé de "name":

Kotlin

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
    if (key == "signature") {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""))
    }
}

Java

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals("signature")) {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""));
    }
}

Enregistrez l'écouteur à l'aide de registerOnSharedPreferenceChangedListener(), comme suit:

Kotlin

preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)

Java

getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);

Kotlin

    val listener: SharedPreferences.OnSharedPreferenceChangeListener =
            SharedPreferences.OnSharedPreferenceChangeListener {...}
    

Java

    SharedPreferences.OnSharedPreferenceChangeListener listener =
            new SharedPreferences.OnSharedPreferenceChangeListener() {...}
    

Pour une gestion appropriée du cycle de vie dans votre Activity ou Fragment, enregistrez cet écouteur et annulez l'enregistrement dans les rappels onResume() et onPause(), comme illustré dans l'exemple suivant:

Kotlin

override fun onResume() {
    super.onResume()
    preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}

override fun onPause() {
    super.onPause()
    preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
}

Java

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
    super.onPause();
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

Utiliser un datastore personnalisé

Bien que nous vous recommandions de conserver les objets Preference à l'aide de SharedPreferences, vous pouvez également utiliser un datastore personnalisé. Un datastore personnalisé peut être utile si votre application conserve des valeurs dans une base de données ou si les valeurs sont spécifiques à un appareil, comme illustré dans les exemples suivants.

Implémenter le datastore

Pour implémenter un datastore personnalisé, créez une classe qui étend PreferenceDataStore. L'exemple suivant crée un datastore qui gère les valeurs String:

Kotlin

class DataStore : PreferenceDataStore() {
    override fun putString(key: String, value: String?) {
        // Save the value somewhere.
    }

    override fun getString(key: String, defValue: String?): String? {
        // Retrieve the value.
    }
}

Java

public class DataStore extends PreferenceDataStore {
    @Override
    public void putString(String key, @Nullable String value) {
        // Save the value somewhere.
    }
    @Override
    @Nullable
    public String getString(String key, @Nullable String defValue) {
        // Retrieve the value.
    }
}

Exécutez toutes les opérations chronophages en dehors du thread principal pour éviter de bloquer l'interface utilisateur. Étant donné qu'il est possible que le Fragment ou l'Activity contenant le datastore soit détruit tout en conservant une valeur, sérialisez les données pour ne pas perdre les valeurs modifiées par l'utilisateur.

Activer le datastore

Après avoir implémenté votre datastore, définissez le nouveau datastore dans onCreatePreferences() afin que les objets Preference conservent les valeurs avec le datastore au lieu d'utiliser la SharedPreferences par défaut. Vous pouvez activer un datastore pour chaque Preference ou pour l'ensemble de la hiérarchie.

Pour activer un datastore personnalisé pour un Preference spécifique, appelez setPreferenceDataStore() sur le Preference, comme illustré dans l'exemple suivant:

Kotlin

val preference: Preference? = findPreference("key")
preference?.preferenceDataStore = dataStore

Java

Preference preference = findPreference("key");
if (preference != null) {
    preference.setPreferenceDataStore(dataStore);
}

Pour activer un datastore personnalisé pour l'ensemble d'une hiérarchie, appelez setPreferenceDataStore() sur PreferenceManager:

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

Un datastore défini pour un Preference spécifique remplace tout datastore défini pour la hiérarchie correspondante. Dans la plupart des cas, vous définissez un datastore pour l'ensemble de la hiérarchie.