SharedPreferences este un depozit de date de tip cheie-valoare în Android, destinat salvării setărilor simple și configurațiilor aplicației. Datele sunt stocate într-un fișier XML pe dispozitiv și sunt accesibile doar în cadrul aplicației care le-a creat. Conform documentației oficiale Android Developers, 2025, SharedPreferences suportă stocarea tipurilor primitive: String, Int, Boolean, Float, Long și Set<String>. Este cea mai simplă și rapidă soluție pentru salvarea unor volume mici de setări ale utilizatorului fără a fi nevoie de interogări SQL sau de lucru direct cu sistemul de fișiere.
Repere principale
SharedPreferences este un mecanism încorporat Android pentru stocarea perechilor cheie-valoare într-un fișier XML pe memoria internă a dispozitivului. Este disponibil începând cu API Level 1 și nu necesită conectarea de biblioteci suplimentare. Scopul principal — salvarea setărilor utilizatorului, stării interfeței, flagurilor de first-launch și a altor date simple care nu necesită o bază de date structurată.
Fiecare fișier SharedPreferences este asociat cu un nume specific și un mod de acces. În mod implicit se utilizează modul Context.MODE_PRIVATE, care limitează accesul la fișier doar aplicației curente. Anterior Android suporta modurile MODE_WORLD_READABLE și MODE_WORLD_WRITEABLE, dar acestea au fost declarate învechite începând cu API Level 17 și complet eliminate în Android 7.0 (API 24) din motive de securitate.
În ciuda simplității sale, SharedPreferences este utilizat în milioane de aplicații Android. Potrivit Google, peste 90% din aplicațiile publicate pe Google Play folosesc SharedPreferences pentru stocarea setărilor. Cu toate acestea, pentru scenarii complexe (volume mari de date, siguranța tipurilor, asincronism) Google recomandă soluții mai moderne, cum ar fi Preferences DataStore din biblioteca Android Jetpack.
Fizic, SharedPreferences este stocat sub formă de fișier XML în directorul aplicației: /data/data/{package_name}/shared_prefs/{file_name}.xml. Fișierul conține elementul rădăcină <map> cu elemente copil <string>, <int>, <boolean>, <float> și <long> în funcție de tipul valorii salvate. Dimensiunea fișierului nu este limitată, dar pentru volume mari de date (peste 100 KB) performanța de citire și scriere începe să scadă considerabil.
Fișierele SharedPreferences nu sunt criptate implicit. Datele sunt stocate în formă deschisă în sistemul de fișiere al dispozitivului. Pentru stocarea datelor sensibile (tokeni, parole) se recomandă utilizarea EncryptedSharedPreferences din biblioteca AndroidX Security, care criptează automat cheile și valorile cu AES256-GCM.
SharedPreferences funcționează pe principiul stocării în cache cu sincronizare periodică pe disc. La prima accesare a fișierului (prin getSharedPreferences), Android încarcă fișierul XML în memoria RAM și îl parsează într-un obiect Map. Toate operațiile ulterioare de citire se execută din memorie, fără re-citire de pe disc. Aceasta asigură o viteză ridicată de acces la date.
Operațiile de scriere utilizează Editor — un buffer intern de modificări. Când dezvoltatorul apelează putString sau putBoolean, modificările sunt stocate în obiectul Editor în memorie. Scrierea efectivă pe disc are loc la apelarea metodei commit (sincron) sau apply (asincron). Până la apelarea acestor metode, datele nu sunt salvate, iar la terminarea forțată a aplicației modificările pot fi pierdute.
Pentru obținerea unei instanțe SharedPreferences se folosesc două metode: getPreferences și getSharedPreferences. Prima este disponibilă doar în interiorul Activity și creează un fișier cu numele Activity. A doua — mai flexibilă, acceptă numele fișierului și modul de acces, și este accesibilă din orice context (Application, Activity, Service). Se recomandă utilizarea getSharedPreferences cu un nume de fișier corespunzător modulului sau funcționalității aplicației.
// Obținerea SharedPreferences
val prefs = context.getSharedPreferences(
"user_settings", Context.MODE_PRIVATE
)
// Scrierea datelor
with(prefs.edit()) {
putString("username", "Ana")
putInt("age", 28)
putBoolean("isLoggedIn", true)
apply()
}
// Citirea datelor
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
La utilizarea MODE_MULTI_PROCESS (învechit) SharedPreferences se sincronizează între procese. Totuși, această sincronizare nu garantează atomicitatea, iar Google recomandă evitarea utilizării SharedPreferences în scenarii multi-process. Pentru astfel de cazuri, este mai bine să folosiți ContentProvider, Room cu acces inter-proces sau DataStore.
SharedPreferences oferă un set de metode pentru citirea datelor după cheie și interfața Editor pentru scriere. Fiecare metodă de citire acceptă doi parametri: cheia și valoarea implicită care este returnată dacă cheia nu este găsită. Valoarea implicită determină și tipul valorii returnate: getString returnează String, getInt — Int și așa mai departe.
| Metoda de citire | Metoda de scriere | Tipul de date |
|---|---|---|
| getString | putString | String |
| getInt | putInt | Int |
| getBoolean | putBoolean | Boolean |
| getFloat | putFloat | Float |
| getLong | putLong | Long |
| getStringSet | putStringSet | Set<String> |
Editor — este obiectul intern al SharedPreferences care colectează modificările în buffer. După efectuarea tuturor modificărilor, dezvoltatorul apelează commit() (scriere sincronă) sau apply() (scriere asincronă). Diferența este critică: commit blochează firul de execuție curent până la scrierea completă pe disc și returnează boolean (succes/eșec), iar apply execută scrierea într-un fir de fundal și returnează imediat controlul, dar nu returnează rezultatul.
Se recomandă utilizarea apply în loc de commit în toate cazurile când nu este necesar să se cunoască rezultatul scrierii. apply este mai rapid și nu blochează firul UI. commit trebuie folosit doar când este crucial să se știe dacă datele au fost salvate cu succes sau la lucrul cu modul multi-process. Pentru ștergerea cheilor individuale se folosește metoda remove, pentru curățarea completă — clear. Toate operațiile de ștergere se execută de asemenea prin Editor.
// Modificări multiple - un singur apply
prefs.edit {
putString("theme", "dark")
putBoolean("notifications", false)
remove("old_key")
}
// Ascultătorul modificării valorilor
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
Log.d("TAG", "S-a modificat cheia: $key")
}
Începând cu Android 12 (API 31), SharedPreferences a fost completată cu suport pentru registerOnSharedPreferenceChangeListener cu dezabonare automată prin Lifecycle. Acest lucru permite evitarea scurgerilor de memorie asociate cu listeneri uitați. În versiunile mai vechi, dezvoltatorul este obligat să apeleze manual unregisterOnSharedPreferenceChangeListener în onDestroy sau onStop al componentei.
În ciuda răspândirii largi, SharedPreferences nu este o soluție universală pentru toate scenariile de stocare a datelor în Android. În funcție de volumul datelor, cerințele de siguranță a tipurilor și performanță, Google recomandă diverse alternative incluse în Android Jetpack și biblioteca standard Android.
| Soluția | Când să utilizați | Dezavantaje |
|---|---|---|
| SharedPreferences | Setări mici (până la 100 de chei) | Fără siguranța tipurilor, citire sincronă |
| DataStore | Setări de complexitate medie cu corutini | Fără compatibilitate retroactivă sub API 14 |
| Room | Date structurate și liste | Excesiv pentru 3–5 setări |
| EncryptedSharedPreferences | Date sensibile și tokeni | Dependență de AndroidX Security |
DataStore — este o bibliotecă Android Jetpack, prezentată de Google ca înlocuitor pentru SharedPreferences. Oferă două variante: Preferences DataStore (cheie-valoare, ca SharedPreferences) și Proto DataStore (stocare tipizată prin Protocol Buffers). DataStore utilizează corutini și Flow pentru lucrul asincron, garantează siguranța tipurilor și gestionează automat migrările de versiuni. Google recomandă DataStore pentru toate proiectele noi.
Principalul avantaj al DataStore — asincronismul la nivel de API. Toate operațiile de citire returnează Flow, iar operațiile de scriere sunt funcții suspend. Acest lucru elimină complet blocarea firului UI, posibilă la citirea sincronă a SharedPreferences. În plus, DataStore garantează consistența datelor: scrierea se execută într-o tranzacție, iar în caz de avarie toate modificările sunt anulate.
Să examinăm un exemplu practic: setările temei (deschis/închis/sistem) într-o aplicație Android. Utilizatorul alege tema, iar alegerea este salvată în SharedPreferences. La pornirile ulterioare ale aplicației, tema se restabilește din setările salvate. Pentru actualizarea reactivă a interfeței se utilizează observarea modificărilor prin SharedPreferences.OnSharedPreferenceChangeListener.
Vom crea clasa ThemePreferences, care încapsulează întreaga lucrare cu SharedPreferences pentru temă. Clasa oferă metodele getTheme (citire), setTheme (scriere) și observeTheme (observare). Numele fișierului de setări va fi „app_preferences" cu modul MODE_PRIVATE. Pentru comoditate, cheile sunt extrase în companion object ca constante.
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())
}
}
}
}
În Activity sau Fragment, obținerea instanței ThemePreferences se realizează prin contextul aplicației. La inițializare se apelează getTheme pentru setarea temei curente. Când utilizatorul alege o temă nouă, se apelează setTheme, iar prin observeTheme interfața se actualizează fără repornirea Activity. Este important să nu uitați să vă dezabonați de la listener în onDestroy pentru a preveni scurgerile de memorie, mai ales dacă Activity este recreat la modificarea configurației.
Pentru aplicațiile cu versiunea țintă minimă Android 12+, se recomandă utilizarea registerOnSharedPreferenceChangeListener împreună cu LifecycleObserver. Acest lucru gestionează automat abonarea și dezabonarea la modificarea ciclului de viață al componentei. Pentru versiunile mai vechi, abonarea și dezabonarea trebuie gestionate manual, ceea ce este o sursă frecventă de erori în aplicațiile de producție care utilizează SharedPreferences.
Întrebări frecvente
SharedPreferences suportă direct doar tipuri primitive și Set<String>. Pentru stocarea obiectelor, acestea trebuie serializate într-un șir JSON prin Gson sau Moshi, salvate prin putString și deserializate la citire. Pentru obiecte complexe cu un număr mare de câmpuri, se recomandă utilizarea Room în loc de SharedPreferences cu serializare JSON.
Da, SharedPreferences este thread-safe. Toate operațiile de citire și scriere sunt sincronizate la nivelul obiectului SharedPreferences și al Editorului său. Totuși, la utilizarea modului multi-process, sincronizarea nu este garantată. Pentru acces concurent din mai multe fire în cadrul unei singure aplicații, SharedPreferences este sigur fără blocări suplimentare.
Pentru curățarea completă a tuturor datelor din SharedPreferences, apelați metoda clear() pe Editor și aplicați modificările prin apply. Dacă trebuie să ștergeți fișierul XML în sine, utilizați deleteSharedPreferences(name) pe context. Ștergerea datelor aplicației prin Setări → Aplicații → Șterge date elimină de asemenea toate fișierele SharedPreferences.
Pentru proiecte noi, Google recomandă DataStore ca înlocuitor pentru SharedPreferences. DataStore asigură lucrul asincron cu corutini, siguranța tipurilor (Proto DataStore) și migrări automate. SharedPreferences trebuie ales doar pentru proiecte cu versiunea minimă sub API 14 sau când este necesară o integrare rapidă fără dependențe suplimentare.
Pentru criptarea datelor, utilizați EncryptedSharedPreferences din biblioteca AndroidX Security. Aceasta criptează automat cheile și valorile cu AES-256 GCM. Procesul de configurare este minim: getSharedPreferences se înlocuiește cu EncryptedSharedPreferences.create specificând cheia principală din Android Keystore.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și