SharedPreferences ist ein Schlüssel-Wert-Datenspeicher auf Android, der zum Speichern einfacher Einstellungen und App-Konfigurationen entwickelt wurde. Die Daten werden in einer XML-Datei auf dem Gerät gespeichert und sind nur innerhalb der App zugänglich, die sie erstellt hat. Laut offizieller Dokumentation Android Developers, 2025 unterstützt SharedPreferences die Speicherung primitiver Typen: String, Int, Boolean, Float, Long und Set<String>. Dies ist die einfachste und schnellste Lösung zum Speichern kleiner Mengen von Benutzereinstellungen, ohne SQL-Abfragen oder direkte Arbeit mit dem Dateisystem.
Wichtige Erkenntnisse
SharedPreferences ist ein integrierter Android-Mechanismus zum Speichern von Schlüssel-Wert-Paaren in einer XML-Datei im internen Speicher des Geräts. Es ist seit API Level 1 verfügbar und erfordert keine zusätzlichen Bibliotheken. Der Hauptzweck besteht darin, Benutzereinstellungen, Schnittstellenzustände, Erststart-Flags und andere einfache Daten zu speichern, die keine strukturierte Datenbank erfordern.
Jede SharedPreferences-Datei ist mit einem bestimmten Namen und Zugriffsmodus verknüpft. Standardmäßig wird der Modus Context.MODE_PRIVATE verwendet, der den Dateizugriff nur auf die aktuelle App beschränkt. Früher unterstützte Android die Modi MODE_WORLD_READABLE und MODE_WORLD_WRITEABLE, die jedoch ab API Level 17 als veraltet eingestuft und aus Sicherheitsgründen in Android 7.0 (API 24) vollständig entfernt wurden.
Trotz seiner Einfachheit wird SharedPreferences in Millionen von Android-Apps verwendet. Laut Google nutzen über 90% der im Google Play veröffentlichten Apps SharedPreferences zum Speichern von Einstellungen. Für komplexe Szenarien (große Datenmengen, Typsicherheit, Asynchronität) empfiehlt Google jedoch modernere Lösungen wie Preferences DataStore aus der Android Jetpack-Bibliothek.
Physisch wird SharedPreferences als XML-Datei im App-Verzeichnis gespeichert: /data/data/{package_name}/shared_prefs/{file_name}.xml. Die Datei enthält ein Wurzelelement <map> mit Kindelementen <string>, <int>, <boolean>, <float> und <long>, abhängig vom gespeicherten Wertetyp. Die Dateigröße ist nicht begrenzt, aber bei großen Datenmengen (über 100 KB) beginnt die Lese- und Schreibleistung merklich nachzulassen.
SharedPreferences-Dateien werden standardmäßig nicht verschlüsselt. Die Daten werden im Klartext auf dem Dateisystem des Geräts gespeichert. Zum Speichern sensibler Daten (Tokens, Passwörter) wird die Verwendung von EncryptedSharedPreferences aus der AndroidX Security-Bibliothek empfohlen, die Schlüssel und Werte automatisch mit AES256-GCM verschlüsselt.
SharedPreferences arbeitet nach dem Prinzip der arbeitsspeicherinternen Zwischenspeicherung mit periodischer Datenträgersynchronisierung. Beim ersten Zugriff auf die Datei (über getSharedPreferences) lädt Android die XML-Datei in den RAM und parst sie in ein Map-Objekt. Alle nachfolgenden Leseoperationen werden aus dem Speicher ausgeführt, ohne erneutes Lesen von der Festplatte. Dies gewährleistet eine hohe Datenzugriffsgeschwindigkeit.
Schreiboperationen verwenden Editor — einen internen Änderungspuffer. Wenn der Entwickler putString oder putBoolean aufruft, werden die Änderungen im Editor-Objekt im Arbeitsspeicher gespeichert. Das eigentliche Schreiben auf die Festplatte erfolgt beim Aufruf der Methode commit (synchron) oder apply (asynchron). Bis zum Aufruf dieser Methoden werden die Daten nicht gespeichert, und bei einem unerwarteten App-Absturz können Änderungen verloren gehen.
Zum Abrufen einer SharedPreferences-Instanz werden zwei Methoden verwendet: getPreferences und getSharedPreferences. Die erste ist nur innerhalb einer Activity verfügbar und erstellt eine Datei mit dem Namen der Activity. Die zweite ist flexibler, akzeptiert einen Dateinamen und Zugriffsmodus und ist von jedem Kontext aus zugänglich (Application, Activity, Service). Es wird empfohlen, getSharedPreferences mit einem Dateinamen zu verwenden, der dem Modul oder der Funktionalität der App entspricht.
// SharedPreferences abrufen
val prefs = context.getSharedPreferences(
"user_settings", Context.MODE_PRIVATE
)
// Daten schreiben
with(prefs.edit()) {
putString("username", "Anna")
putInt("age", 28)
putBoolean("isLoggedIn", true)
apply()
}
// Daten lesen
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
Bei Verwendung von MODE_MULTI_PROCESS (veraltet) synchronisiert SharedPreferences zwischen Prozessen. Diese Synchronisierung garantiert jedoch keine Atomizität, und Google empfiehlt, SharedPreferences in Multiprozess-Szenarien zu vermeiden. Für solche Fälle ist es besser, ContentProvider, Room mit prozessübergreifendem Zugriff oder DataStore zu verwenden.
SharedPreferences bietet eine Reihe von Methoden zum Lesen von Daten nach Schlüssel und die Editor-Schnittstelle zum Schreiben. Jede Lesemethode akzeptiert zwei Parameter: einen Schlüssel und einen Standardwert, der zurückgegeben wird, wenn der Schlüssel nicht gefunden wird. Der Standardwert bestimmt auch den Rückgabetyp: getString gibt String zurück, getInt gibt Int zurück und so weiter.
| Lesemethode | Schreibmethode | Datentyp |
|---|---|---|
| getString | putString | String |
| getInt | putInt | Int |
| getBoolean | putBoolean | Boolean |
| getFloat | putFloat | Float |
| getLong | putLong | Long |
| getStringSet | putStringSet | Set<String> |
Editor ist ein internes SharedPreferences-Objekt, das Änderungen in einem Puffer sammelt. Nachdem alle Änderungen vorgenommen wurden, ruft der Entwickler commit() (synchrones Schreiben) oder apply() (asynchrones Schreiben) auf. Der Unterschied ist kritisch: commit blockiert den aktuellen Thread bis zum vollständigen Schreiben auf die Festplatte und gibt einen boolean (Erfolg/Misserfolg) zurück, während apply das Schreiben in einem Hintergrundthread durchführt und sofort die Kontrolle zurückgibt, aber kein Ergebnis zurückliefert.
Es wird empfohlen, in allen Fällen, in denen das Schreibergebnis nicht bekannt sein muss, apply anstelle von commit zu verwenden. apply ist schneller und blockiert nicht den UI-Thread. commit sollte nur verwendet werden, wenn es entscheidend ist zu wissen, ob die Daten erfolgreich gespeichert wurden, oder bei der Arbeit mit dem Multiprozess-Modus. Zum Entfernen einzelner Schlüssel wird die Methode remove verwendet, zum vollständigen Löschen — clear. Alle Löschvorgänge werden ebenfalls über Editor ausgeführt.
// Mehrere Änderungen - ein apply
prefs.edit {
putString("theme", "dark")
putBoolean("notifications", false)
remove("old_key")
}
// Wertänderungs-Listener
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
Log.d("TAG", "Schlüssel geändert: $key")
}
Ab Android 12 (API 31) wurde SharedPreferences um die Unterstützung von registerOnSharedPreferenceChangeListener mit automatischer Abbestellung über Lifecycle erweitert. Dies hilft, Speicherlecks zu vermeiden, die mit vergessenen Listenern verbunden sind. In älteren Versionen muss der Entwickler manuell unregisterOnSharedPreferenceChangeListener in onDestroy oder onStop der Komponente aufrufen.
Trotz seiner weiten Verbreitung ist SharedPreferences keine universelle Lösung für alle Datenspeicherungsszenarien auf Android. Abhängig von Datenvolumen, Typsicherheitsanforderungen und Leistung empfiehlt Google verschiedene Alternativen, die in Android Jetpack und der standardmäßigen Android-Bibliothek enthalten sind.
| Lösung | Wann verwenden | Nachteile |
|---|---|---|
| SharedPreferences | Kleine Einstellungen (bis zu 100 Schlüssel) | Keine Typsicherheit, synchrones Lesen |
| DataStore | Einstellungen mittlerer Komplexität mit Koroutinen | Keine Abwärtskompatibilität unter API 14 |
| Room | Strukturierte Daten und Listen | Überdimensioniert für 3-5 Einstellungen |
| EncryptedSharedPreferences | Sensible Daten und Tokens | Abhängigkeit von AndroidX Security |
DataStore ist eine Android Jetpack-Bibliothek, die von Google als Ersatz für SharedPreferences vorgestellt wurde. Sie bietet zwei Varianten: Preferences DataStore (Schlüssel-Wert, wie SharedPreferences) und Proto DataStore (typisierte Speicherung über Protocol Buffers). DataStore verwendet Koroutinen und Flow für asynchrone Operationen, garantiert Typsicherheit und behandelt automatisch Versionsmigrationen. Google empfiehlt DataStore für alle neuen Projekte.
Der Hauptvorteil von DataStore ist die Asynchronität auf API-Ebene. Alle Leseoperationen geben Flow zurück, und Schreiboperationen sind Suspend-Funktionen. Dies eliminiert vollständig die Blockierung des UI-Threads, die bei synchronem Lesen von SharedPreferences auftreten kann. Darüber hinaus garantiert DataStore Datenkonsistenz: Das Schreiben erfolgt in einer Transaktion, und bei einem Fehler werden alle Änderungen zurückgesetzt.
Betrachten wir ein praktisches Beispiel: Themeneinstellungen (hell/dunkel/system) in einer Android-App. Der Benutzer wählt ein Thema aus, und die Auswahl wird in SharedPreferences gespeichert. Bei nachfolgenden App-Starts wird das Thema aus den gespeicherten Einstellungen wiederhergestellt. Für reaktive UI-Updates wird die Beobachtung von Änderungen über SharedPreferences.OnSharedPreferenceChangeListener verwendet.
Erstellen wir eine Klasse ThemePreferences, die die gesamte Arbeit mit SharedPreferences für das Thema kapselt. Die Klasse bietet Methoden getTheme (Lesen), setTheme (Schreiben) und observeTheme (Beobachten). Der Dateiname der Einstellungen lautet „app_preferences“ mit dem Modus MODE_PRIVATE. Der Einfachheit halber werden die Schlüssel in einem Companion-Objekt als Konstanten abgelegt.
class ThemePreferences(context: Context) {
companion object {
private const val PREF_NAME = "app_preferences"
private const val KEY_THEME = "theme_mode"
const val THEME_LIGHT = "light"
const val THEME_DARK = "dark"
const val THEME_SYSTEM = "system"
}
private val prefs = context
.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
fun getTheme(): String =
prefs.getString(KEY_THEME, THEME_SYSTEM) ?: THEME_SYSTEM
fun setTheme(theme: String) {
prefs.edit { putString(KEY_THEME, theme) }
}
fun observeTheme(callback: (String) -> Unit) {
prefs.registerOnSharedPreferenceChangeListener { _, key ->
if (key == KEY_THEME) {
callback.invoke(getTheme())
}
}
}
}
In einer Activity oder einem Fragment erfolgt das Abrufen einer ThemePreferences-Instanz über den App-Kontext. Bei der Initialisierung wird getTheme aufgerufen, um das aktuelle Thema festzulegen. Wenn der Benutzer ein neues Thema auswählt, wird setTheme aufgerufen, und über observeTheme wird die Benutzeroberfläche aktualisiert, ohne die Activity neu zu starten. Es ist wichtig, das Abonnement des Listeners in onDestroy zu kündigen, um Speicherlecks zu vermeiden, insbesondere wenn die Activity bei Konfigurationsänderungen neu erstellt wird.
Für Apps mit einem Mindestziel von Android 12+ wird die Verwendung von registerOnSharedPreferenceChangeListener zusammen mit LifecycleObserver empfohlen. Dies verwaltet Abonnement und Kündigung automatisch bei Änderungen des Komponentenlebenszyklus. Für ältere Versionen müssen Abonnement und Kündigung manuell verwaltet werden, was eine häufige Fehlerquelle in Produktions-Apps ist, die SharedPreferences verwenden.
Häufig gestellte Fragen
SharedPreferences unterstützt direkt nur primitive Typen und Set<String>. Zum Speichern von Objekten müssen diese über Gson oder Moshi in einen JSON-String serialisiert, über putString gespeichert und beim Lesen deserialisiert werden. Für komplexe Objekte mit vielen Feldern wird die Verwendung von Room anstelle von SharedPreferences mit JSON-Serialisierung empfohlen.
Ja, SharedPreferences ist thread-sicher. Alle Lese- und Schreiboperationen werden auf der Ebene des SharedPreferences-Objekts und seines Editors synchronisiert. Bei Verwendung des Multiprozess-Modus ist die Synchronisierung jedoch nicht gewährleistet. Für den gleichzeitigen Zugriff aus mehreren Threads innerhalb einer einzelnen App ist SharedPreferences ohne zusätzliche Sperren sicher.
Um alle Daten aus SharedPreferences vollständig zu löschen, rufen Sie die Methode clear() auf dem Editor auf und wenden Sie die Änderungen über apply an. Wenn Sie die XML-Datei selbst löschen müssen, verwenden Sie deleteSharedPreferences(name) auf dem Kontext. Das Löschen von App-Daten über Einstellungen → Apps → Daten löschen entfernt ebenfalls alle SharedPreferences-Dateien.
Für neue Projekte empfiehlt Google DataStore als Ersatz für SharedPreferences. DataStore bietet asynchrone Operationen mit Koroutinen, Typsicherheit (Proto DataStore) und automatische Migrationen. SharedPreferences sollte nur für Projekte mit einer Mindestversion unter API 14 gewählt werden oder wenn eine schnelle Integration ohne zusätzliche Abhängigkeiten erforderlich ist.
Zur Datenverschlüsselung verwenden Sie EncryptedSharedPreferences aus der AndroidX Security-Bibliothek. Diese verschlüsselt Schlüssel und Werte automatisch mit AES-256 GCM. Der Einrichtungsprozess ist minimal: getSharedPreferences wird durch EncryptedSharedPreferences.create mit Angabe eines Masterschlüssels aus Android Keystore ersetzt.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch