Alles über DataStore-Einstellungen. In diesem Beitrag werden wir uns ansehen… | von Simona Stojanovic Android-Entwickler Januar 2022

Wir werden uns diesen Beitrag ansehen DataStore-Einstellungeneiner von zwei Datenspeicher Implementierung. Wir werden weitermachen, wie erstellen, Daten lesen und schreiben und Ausnahmen behandelnund all das sollte Ihnen hoffentlich genügend Informationen liefern, um zu entscheiden, ob dies die richtige Wahl für Ihre Anwendung ist.
Einstellungen DataStore-Verwendungen Schlüssel/Wert-Paare um kleinere Datensätze zu speichern, ohne zuerst das Schema zu definieren. Dies könnte Sie daran erinnern SharedPreferences
, aber nur in der Art und Weise, wie es Ihre Datenmodelle strukturiert. Es gibt ein verschiedene Vorteile bringt der DataStore durch seine SharedPreferences
Vorgänger. Melden Sie sich schnell bei uns zurück vorherigen Post und schauen Sie sich den detaillierten Vergleich an, den wir dort gemacht haben. Wir werden uns das Folgende ansehen Preferences DataStore
wie nur Preferences
wenn nicht anders angegeben.
Für eine kurze Zusammenfassung:
- Bietet ein vollständig asynchrone API zum Herunterladen und Speichern von Daten mit der Kraft von Kotlin Korutina
- Es bietet keine gebrauchsfertige synchrone Unterstützung – vermeidet direkt jegliche Arbeit, die den UI-Thread blockiert
- Es stützt sich auf den internen Fehlersignalisierungsmechanismus von Flow, der Ihnen dies ermöglicht Ausnahmen sicher erfassen und verarbeiten beim Lesen oder Schreiben von Daten
- Verarbeitet Transaktionsdatenaktualisierungen in einer Atomares Lesen-Modifizieren-Schreiben Arbeit, Bereitstellung stark SÄURE Garantien
- Erlaubt einfache und schnelle Datenmigration
- Wollen schnell migrieren von
SharedPreferences
mit minimale Änderungen und Sie fühlen sich ohne volle Sicherheit sicher genug? Wählen Einstellungen über Proto
Lassen Sie uns nun in etwas Code eintauchen und lernen, wie Einstellungen implementiert werden sollten.
Wir werden verwenden DataStore-Einstellungen Codelab-Code. Wenn Sie an einem praktischeren Ansatz zur Implementierung interessiert sind, empfehlen wir Ihnen wirklich, es durchzugehen Arbeiten Sie mit DataStore-Einstellungen codelab allein.
Diese Beispielanwendung zeigt eine Liste von Aufgaben an, und der Benutzer kann sie nach ihrem abgeschlossenen Status filtern oder nach Priorität und Frist sortieren. Wir möchten ihre Auswahl speichern boolean für abgeschlossene Aufgaben ia Aufzählung sortieren im Datenspeicher.
Beginnen wir mit dem Hinzufügen der erforderlichen Abhängigkeiten:
💡 Ein kurzer Tipp: Wenn Sie Ihre Konstruktion minimieren möchten, fügen Sie Ihrer eigenen eine zusätzliche Regel hinzu proguard-rules.pro
Datei, um zu verhindern, dass Ihre Felder gelöscht werden:
Sie interagieren mit den im DataStore gespeicherten Daten über eine Instanz DataStore<Preferences>
. DataStore
ist eine Schnittstelle, die den Zugriff auf dauerhafte Informationen gewährt. Einstellungen ist eine abstrakte Klasse ähnlich einer generischen Karte, die insbesondere in der Implementierung des Preferences DataStore verwendet wird, um Schlüssel-Wert-Paare Ihrer Daten zu verfolgen. Wir werden darüber sprechen MutablePreferences
Unterklasse, wenn wir über das Schreiben von Daten sprechen.
Es wird empfohlen, zum Erstellen dieser Instanz einen Delegaten zu verwenden preferencesDataStore
und Pass erforderlich name
Streit. Dieser Delegierte ist a Kotlin-Eigenschaftserweiterung dessen Empfängertyp eine Instanz sein muss Context
anschließend für den Bau benötigt File
Objekt, in dem DataStore Daten speichert:
Sie sollten nicht mehr als eine DataStore-Instanz für eine bestimmte Datei erstellen, weil es die gesamte Funktionalität des DataStore ruinieren kann. Daher können Sie ein Delegate-Konstrukt einmal auf der obersten Ebene Ihrer Kotlin-Datei hinzufügen und es in der gesamten Anwendung verwenden, um es als zu übergeben Einzelling. Wie das mit einer Suchtspritze geht, sehen wir uns in späteren Beiträgen an.
Schlüssel definieren
DataStore bietet eine schnelle Möglichkeit, Schlüssel für verschiedene Datentypen zu erstellen, z booleanPreferencesKey
, intPreferencesKey
und vieles mehr – Sie müssen nur bestehen Schlüsselname als Wert. Obwohl dies einige Einschränkungen für Datentypen mit sich bringt, sollten Sie dies im Hinterkopf behalten bietet keine endgültige Typsicherheit. Indem wir den bevorzugten Schlüssel eines bestimmten Typs bestimmen, hoffen wir das Beste und verlassen uns auf unsere Annahmen der Wert eines bestimmten Typs würde zurückgegeben. Wenn Sie der Meinung sind, dass Ihr Code so strukturiert ist, dass er sicher zu handhaben ist, können Sie gerne mit den Einstellungen fortfahren. Wenn nicht, erwägen Sie, den Bruder von Preferences zu verwenden, Proto-DataStorewie er prophezeit vollständige Sicherheit.
In unserer Anwendung UserPreferencesRepository
Wir geben alle Schlüssel an, die zur Strukturierung der Schlüssel/Wert-Paare unserer persistenten Daten erforderlich sind:
Zum Auslesen gespeicherter Daten, u UserPreferencesRepository
wir belichten a Flow<Preferences>
von dataStore.data
. Dies ermöglicht ein effizientes Vorgehen der letzte erhaltene Zustand ich Sendungen bei jeder Änderung. Mithilfe von Kotlin-Datenklassen können wir alle Sendungen beobachten und den Datenspeicher transformieren Preferences
unterliegen unseren UserPreferences
Modell, nur verwenden Schlüssel/Wert-Paare wir sind interessiert an:
Flow wird immer entweder einen Wert ausgeben oder verwerfen Sie die Ausnahme beim Versuch, von der Festplatte zu lesen. Wir werden uns in späteren Abschnitten mit der Behandlung von Ausnahmen befassen. Der DataStore stellt außerdem sicher, dass die Arbeit immer erledigt wird Dispatchers.IO
Ihr UI-Thread wird also nicht blockiert.
🚨 Erstellen Sie keine Cache-Repositories um den aktuellen Stand Ihrer Präferenzdaten abzubilden. Damit erlischt die DataStore-Garantie für Datenkonsistenz. Wenn Sie eine Aufnahme Ihrer Daten ohne ein Abonnement für weitere Flow-Shows benötigen, verwenden Sie sie stattdessen dataStore.data.first()
:
Wir werden die Aussetzung verwenden, um Daten zu schreiben DataStore<Preferences>.edit(transform: suspend (MutablePreferences) -> Unit)
Funktion. Lassen Sie es uns aufschlüsseln:
DataStore<Preferences>
Schnittstelle – wir verwenden derzeit den Datenspeicher als BetonPreferences
Implementierungtransform: suspend (MutablePreferences) -> Unit
– ein Suspend-Block, der verwendet wird, um diese Änderungen auf unsere persistenten Daten anzuwendenMutablePreferences
– variable UnterklassePreferences
ähnlichMutableMap
wodurch wir Änderungen an unseren Schlüssel/Wert-Paaren vornehmen können
Als Beispiel werden wir unsere ändern SHOW_COMPLETED
Flagge:
Die Bearbeitung von Daten erfolgt transaktional in einem Atomare Read-Modify-Write-Operation. Das bedeutet, dass es eine bestimmte Abfolge von Datenverarbeitungsvorgängen garantiert, während derer Daten für andere Threads gesperrt sind Konsistenz ich verhindert Rennbedingungen. Nur nach transform
ich edit
Corutins erfolgreich abgeschlossen, Daten werden dauerhaft auf der Festplatte gespeichert und datastore.data
Der Fluss wird die Aktualisierung widerspiegeln.
🚨 Beachten Sie, dass dies die einzige Möglichkeit ist, den Status des DataStore zu ändern. Wartung u MutablePreferences
Referenz und manuelle Mutation danach transform
vervollständigt ändert die permanenten Daten nicht im DataStore, also sollten Sie nicht versuchen, es zu ändern MutablePreferences
außen transform
Block.
Wenn der Schreibvorgang aus irgendeinem Grund fehlschlägt, wird die Transaktion beendet und eine Ausnahme ausgelöst.
Wenn Sie es zuvor verwendet haben SharedPreferences
in Ihrer Bewerbung und möchten Ihre Daten sicher an Preferences übertragen, können Sie verwenden SharedPreferencesMigration
. Dazu braucht es Kontext, SharedPreferences
den Namen und den optionalen Schlüsselsatz, den Sie migrieren möchten (oder lassen Sie es einfach so Ursprünglich MIGRATE_ALL_KEYS
Wert).
Ansehen SharedPreferencesMigration
Implementierung sehen Sie a getMigrationFunction()
die dafür verantwortlich ist, alle erforderlichen, gespeicherten Schlüssel/Wert-Paare abzurufen und sie zu den Einstellungen hinzuzufügen gleichen Tasten. Bestehen SharedPreferencesMigration
über dem produceMigrations
ParameterpreferencesDataStore
delegieren an einfach zu migrieren:
produceMigrations
wird dafür sorgen getMigrationFunction()
wurde gestartet vor einem möglichen Zugriff auf Daten im Datenspeicher. Das bedeutet Ihre Migration ihm muss es gelungen sein bevor der DataStore weitere Werte aussendet und bevor er mit neuen Datenänderungen beginnt. Sobald Sie erfolgreich migriert haben, können Sie die Verwendung sicher einstellen SharedPreferences
wie Schlüssel nur einmal migriert und dann ENTFERNT von SharedPreferences
.
Der produceMigrations
akzeptiert die Liste DataMigration
. Wir werden in späteren Episoden sehen, wie wir dies für andere Arten von Datenmigrationen verwenden können. Wenn Sie nicht migrieren müssen, können Sie dies ignorieren, da es eine gibt Ursprünglich listOf()
bereitgestellt schon.
Einer der Hauptvorteile von DataStore gegenüber SharedPreferences
ist seine ein geordneter Mechanismus zum Erfassen und Behandeln von Ausnahmen. Während SharedPreferences
wirft Parsing-Fehler als Laufzeitausnahmen aus und lässt Raum für unerwartete, nicht abgefangene Abstürze, DataStore wirft aus IOException
wenn beim Lesen/Schreiben von Daten ein Fehler auftritt.
Wir können dies sicher lösen, indem wir verwenden catch()
Flow-Operator kurz davor map()
und Rundfunk emptyPreferences()
:
Oder mit dem einfachen try-catch
Blockschreiben:
Wenn eine andere Art von Ausnahme ausgelöst wird, sollten Sie sie besser erneut auslösen.
Wir deckten ab DataStore-Einstellungen Implementierung – wann und wie man damit Daten liest und schreibt, wie man mit Fehlern umgeht und wie man sie überwindet SharedPreferences
. Im nächsten Beitrag werden wir die gleichen Themen mit behandeln Proto-DataStore Umsetzung, also bleiben.