Gespeicherte Einstellungen verwenden Teil von Android Jetpack

In diesem Dokument wird beschrieben, wie Preference-Werte gespeichert und verwendet werden, die von der Einstellungsbibliothek gespeichert werden.

Datenspeicherung der Präferenzen

In diesem Abschnitt wird beschrieben, wie ein Preference Daten dauerhaft speichert.

Freigegebene Einstellungen

Standardmäßig verwendet ein Preference zum Speichern von Werten SharedPreferences. Die SharedPreferences API unterstützt das Lesen und Schreiben einfacher Schlüssel/Wert-Paare aus einer Datei, die über Anwendungssitzungen hinweg gespeichert wird. Die Einstellungsbibliothek verwendet eine private SharedPreferences-Instanz, sodass nur Ihre Anwendung darauf zugreifen kann.

Nehmen wir beispielsweise Folgendes an SwitchPreferenceCompat:

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

Wenn ein Nutzer diesen Schalter auf „An“ setzt, wird die Datei SharedPreferences mit dem Schlüssel/Wert-Paar "notifications" : "true" aktualisiert. Der verwendete Schlüssel ist mit dem Schlüsselsatz für Preference identisch.

Weitere Informationen zur SharedPreferences API finden Sie unter Daten zu Schlüssel/Wert-Paaren speichern.

Informationen zu den verschiedenen Möglichkeiten zum Speichern von Daten unter Android findest du unter Daten- und Dateispeicher – Übersicht.

Präferenzdatenspeicher

Obwohl die Einstellungsbibliothek Daten mit SharedPreferences standardmäßig beibehält, ist SharedPreferences nicht immer eine ideale Lösung. Wenn sich beispielsweise ein Nutzer für Ihre Anwendung anmelden muss, können Sie die Anwendungseinstellungen in der Cloud beibehalten, damit sie auf anderen Geräten und Plattformen übernommen werden. Wenn Ihre App gerätespezifische Konfigurationsoptionen hat, hat auch jeder Nutzer auf dem Gerät eigene Einstellungen, sodass SharedPreferences keine ideale Lösung ist.

Mit einem PreferenceDataStore können Sie ein benutzerdefiniertes Speicher-Back-End verwenden, um Preference-Werte beizubehalten. Weitere Informationen finden Sie unter Benutzerdefinierten Datenspeicher verwenden.

Einstellungen für Leseeinstellungen

Rufen Sie PreferenceManager.getDefaultSharedPreferences() auf, um das verwendete SharedPreferences-Objekt abzurufen. Obwohl diese Methode überall in Ihrer Anwendung funktioniert, empfehlen wir, die Anwendung in Ebenen aufzuteilen. Weitere Informationen finden Sie unter Datenschicht.

Beispiel: Bei einem EditTextPreference mit dem Schlüssel "signature" so:

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

So können Sie den gespeicherten Wert für diese Preference global abrufen:

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", "");

Auf Änderungen an Einstellungswerten warten

Sie können zwischen zwei Schnittstellen wählen, um auf Änderungen an Preference-Werten zu warten:

In der folgenden Tabelle sehen Sie, wie sich die beiden Oberflächen unterscheiden:

OnPreferenceChangeListener OnSharedPreferenceChangeListener
Wird für ein einzelnes Preference festgelegt. Gilt für alle Preference-Objekte.
Wird aufgerufen, wenn ein Preference im Begriff ist, den gespeicherten Wert zu ändern, auch wenn der ausstehende Wert mit dem gespeicherten Wert übereinstimmt. Wird nur aufgerufen, wenn sich der für Preference gespeicherte Wert ändert.
Wird nur über die Preference-Bibliothek aufgerufen. Der gespeicherte Wert kann in einem separaten Teil der Anwendung geändert werden. Wird aufgerufen, wenn sich der gespeicherte Wert ändert, auch wenn er aus einem anderen Teil der Anwendung stammt.
Wird aufgerufen, bevor der ausstehende Wert gespeichert wird. Wird aufgerufen, nachdem der Wert gespeichert wurde.
Wird bei Verwendung von SharedPreferences oder PreferenceDataStore aufgerufen. Wird nur bei Verwendung von SharedPreferences aufgerufen.

OnPreferredChangeListener implementieren

Durch Implementieren eines OnPreferenceChangeListener können Sie auf eine ausstehende Änderung des Werts von Preference warten. Anschließend können Sie prüfen, ob die Änderung erfolgt. Der folgende Code zeigt beispielsweise, wie auf eine Änderung des Werts eines EditTextPreference mit dem Schlüssel "name" gewartet wird:

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;
}

Als Nächstes müssen Sie diesen Listener direkt mit setOnPreferenceChangeListener() festlegen:

Kotlin

preference.onPreferenceChangeListener = ...

Java

preference.setOnPreferenceChangeListener(...);

OnSharedPreferencesChangeListener implementieren

Wenn Sie Preference-Werte mit SharedPreferences beibehalten, können Sie auch einen SharedPreferences.OnSharedPreferenceChangeListener verwenden, um auf Änderungen zu warten. So kannst du beobachten, wenn sich die von der Preference gespeicherten Werte ändern, z. B. beim Synchronisieren von Einstellungen mit einem Server. Das folgende Beispiel zeigt, wie Sie auf eine Änderung des Werts eines EditTextPreference mit dem Schlüssel "name" warten:

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, ""));
    }
}

Registrieren Sie den Listener mit registerOnSharedPreferenceChangedListener() so:

Kotlin

preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)

Java

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

Kotlin

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

Java

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

Damit der Lebenszyklus in Activity oder Fragment richtig verwaltet werden kann, sollten Sie diesen Listener wie im folgenden Beispiel in den Callbacks onResume() und onPause() registrieren und seine Registrierung aufheben:

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);
}

Benutzerdefinierten Datenspeicher verwenden

Obwohl wir empfehlen, Preference-Objekte mit SharedPreferences beizubehalten, können Sie auch einen benutzerdefinierten Datenspeicher verwenden. Ein benutzerdefinierter Datenspeicher kann nützlich sein, wenn Ihre Anwendung Werte in einer Datenbank beibehält oder wenn die Werte gerätespezifisch sind, wie in den folgenden Beispielen gezeigt.

Datastore implementieren

Zum Implementieren eines benutzerdefinierten Datenspeichers müssen Sie eine Klasse erstellen, die PreferenceDataStore erweitert. Im folgenden Beispiel wird ein Datenspeicher erstellt, der String-Werte verarbeitet:

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.
    }
}

Führen Sie alle zeitaufwendigen Vorgänge außerhalb des Hauptthreads aus, um die Benutzeroberfläche nicht zu blockieren. Da es möglich ist, dass Fragment oder Activity, die den Datenspeicher enthalten, gelöscht werden, während ein Wert beibehalten wird, sollten Sie die Daten so priorisieren, dass keine vom Nutzer geänderten Werte verloren gehen.

Datenspeicher aktivieren

Nachdem Sie Ihren Datenspeicher implementiert haben, legen Sie den neuen Datenspeicher in onCreatePreferences() fest, damit Preference-Objekte Werte mit dem Datenspeicher beibehalten, anstatt den Standardwert SharedPreferences zu verwenden. Sie können einen Datenspeicher für jeden Preference oder für die gesamte Hierarchie aktivieren.

Wenn Sie einen benutzerdefinierten Datenspeicher für eine bestimmte Preference aktivieren möchten, rufen Sie setPreferenceDataStore() für Preference auf, wie im folgenden Beispiel gezeigt:

Kotlin

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

Java

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

Rufen Sie setPreferenceDataStore() für das PreferenceManager auf, um einen benutzerdefinierten Datenspeicher für eine gesamte Hierarchie zu aktivieren:

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

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

Ein Datenspeicher, der für eine bestimmte Preference festgelegt ist, überschreibt jeden Datenspeicher, der für die entsprechende Hierarchie festgelegt ist. In den meisten Fällen legen Sie einen Datenspeicher für die gesamte Hierarchie fest.