Το SharedPreferences είναι ένας αποθηκευτικός χώρος δεδομένων κλειδιού-τιμής στο Android, σχεδιασμένος για την αποθήκευση απλών ρυθμίσεων και παραμέτρων εφαρμογής. Τα δεδομένα αποθηκεύονται σε ένα XML αρχείο στη συσκευή και είναι προσβάσιμα μόνο εντός της εφαρμογής που τα δημιούργησε. Σύμφωνα με την επίσημη τεκμηρίωση Android Developers, 2025, το SharedPreferences υποστηρίζει την αποθήκευση πρωτόγονων τύπων: String, Int, Boolean, Float, Long και Set<String>. Είναι η απλούστερη και ταχύτερη λύση για την αποθήκευση μικρών όγκων ρυθμίσεων χρήστη χωρίς την ανάγκη SQL ερωτημάτων ή άμεσης εργασίας με το σύστημα αρχείων.
Κύρια Σημεία
SharedPreferences είναι ένας ενσωματωμένος μηχανισμός Android για την αποθήκευση ζευγών κλειδιού-τιμής σε ένα XML αρχείο στην εσωτερική μνήμη της συσκευής. Είναι διαθέσιμο από το API Level 1 και δεν απαιτεί τη σύνδεση πρόσθετων βιβλιοθηκών. Κύριος σκοπός — αποθήκευση ρυθμίσεων χρήστη, κατάστασης διεπαφής, σημαιών first-launch και άλλων απλών δεδομένων που δεν απαιτούν δομημένη βάση δεδομένων.
Κάθε αρχείο SharedPreferences συνδέεται με ένα συγκεκριμένο όνομα και λειτουργία πρόσβασης. Από προεπιλογή χρησιμοποιείται η λειτουργία Context.MODE_PRIVATE, η οποία περιορίζει την πρόσβαση στο αρχείο μόνο στην τρέχουσα εφαρμογή. Παλαιότερα το Android υποστήριζε τις λειτουργίες MODE_WORLD_READABLE και MODE_WORLD_WRITEABLE, αλλά αυτές κηρύχθηκαν απαρχαιωμένες από το API Level 17 και αφαιρέθηκαν πλήρως στο Android 7.0 (API 24) για λόγους ασφαλείας.
Παρά την απλότητά του, το SharedPreferences χρησιμοποιείται σε εκατομμύρια εφαρμογές Android. Σύμφωνα με την Google, πάνω από το 90% των εφαρμογών που δημοσιεύονται στο Google Play χρησιμοποιούν SharedPreferences για την αποθήκευση ρυθμίσεων. Ωστόσο, για σύνθετα σενάρια (μεγάλοι όγκοι δεδομένων, ασφάλεια τύπων, ασυγχρονισμός) η Google συνιστά πιο σύγχρονες λύσεις, όπως το Preferences DataStore από τη βιβλιοθήκη Android Jetpack.
Φυσικά, το SharedPreferences αποθηκεύεται ως XML αρχείο στον κατάλογο της εφαρμογής: /data/data/{package_name}/shared_prefs/{file_name}.xml. Το αρχείο περιέχει το ριζικό στοιχείο <map> με θυγατρικά στοιχεία <string>, <int>, <boolean>, <float> και <long> ανάλογα με τον τύπο της αποθηκευμένης τιμής. Το μέγεθος του αρχείου δεν είναι περιορισμένο, αλλά για μεγάλους όγκους δεδομένων (πάνω από 100 KB) η απόδοση ανάγνωσης και εγγραφής αρχίζει να μειώνεται αισθητά.
Τα αρχεία SharedPreferences δεν είναι κρυπτογραφημένα από προεπιλογή. Τα δεδομένα αποθηκεύονται σε ανοιχτή μορφή στο σύστημα αρχείων της συσκευής. Για την αποθήκευση ευαίσθητων δεδομένων (διακριτικά, κωδικοί πρόσβασης) συνιστάται η χρήση του EncryptedSharedPreferences από τη βιβλιοθήκη AndroidX Security, η οποία κρυπτογραφεί αυτόματα τα κλειδιά και τις τιμές με AES256-GCM.
SharedPreferences λειτουργεί με βάση την αρχή της προσωρινής αποθήκευσης στη μνήμη με περιοδικό συγχρονισμό στο δίσκο. Κατά την πρώτη πρόσβαση στο αρχείο (μέσω getSharedPreferences), το Android φορτώνει το XML αρχείο στη RAM και το αναλύει σε ένα αντικείμενο Map. Όλες οι επόμενες λειτουργίες ανάγνωσης εκτελούνται από τη μνήμη, χωρίς εκ νέου ανάγνωση από το δίσκο. Αυτό εξασφαλίζει υψηλή ταχύτητα πρόσβασης στα δεδομένα.
Οι λειτουργίες εγγραφής χρησιμοποιούν το Editor — ένα εσωτερικό buffer αλλαγών. Όταν ο προγραμματιστής καλεί putString ή putBoolean, οι αλλαγές αποθηκεύονται στο αντικείμενο Editor στη μνήμη. Η πραγματική εγγραφή στο δίσκο γίνεται κατά την κλήση της μεθόδου commit (σύγχρονα) ή apply (ασύγχρονα). Μέχρι την κλήση αυτών των μεθόδων, τα δεδομένα δεν αποθηκεύονται και σε περίπτωση απότομης διακοπής της εφαρμογής, οι αλλαγές μπορεί να χαθούν.
Για τη λήψη μιας παρουσίας SharedPreferences χρησιμοποιούνται δύο μέθοδοι: getPreferences και getSharedPreferences. Η πρώτη είναι διαθέσιμη μόνο εντός του Activity και δημιουργεί ένα αρχείο με το όνομα του Activity. Η δεύτερη είναι πιο ευέλικτη, δέχεται όνομα αρχείου και λειτουργία πρόσβασης, και είναι διαθέσιμη από οποιοδήποτε πλαίσιο (Application, Activity, Service). Συνιστάται η χρήση getSharedPreferences με όνομα αρχείου που αντιστοιχεί στην ενότητα ή λειτουργικότητα της εφαρμογής.
// Λήψη SharedPreferences
val prefs = context.getSharedPreferences(
"user_settings", Context.MODE_PRIVATE
)
// Εγγραφή δεδομένων
with(prefs.edit()) {
putString("username", "Άννα")
putInt("age", 28)
putBoolean("isLoggedIn", true)
apply()
}
// Ανάγνωση δεδομένων
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
Κατά τη χρήση MODE_MULTI_PROCESS (απαρχαιωμένο) το SharedPreferences συγχρονίζεται μεταξύ διεργασιών. Ωστόσο, αυτός ο συγχρονισμός δεν εγγυάται ατομικότητα, και η Google συνιστά την αποφυγή χρήσης SharedPreferences σε σενάρια multi-process. Για τέτοιες περιπτώσεις, είναι καλύτερο να χρησιμοποιείτε ContentProvider, Room με πρόσβαση μεταξύ διεργασιών ή DataStore.
SharedPreferences παρέχει ένα σύνολο μεθόδων για ανάγνωση δεδομένων βάσει κλειδιού και τη διεπαφή Editor για εγγραφή. Κάθε μέθοδος ανάγνωσης δέχεται δύο παραμέτρους: το κλειδί και την προεπιλεγμένη τιμή που επιστρέφεται αν το κλειδί δεν βρεθεί. Η προεπιλεγμένη τιμή καθορίζει επίσης τον τύπο της επιστρεφόμενης τιμής: η getString επιστρέφει String, η getInt — Int και ούτω καθεξής.
| Μέθοδος ανάγνωσης | Μέθοδος εγγραφής | Τύπος δεδομένων |
|---|---|---|
| getString | putString | String |
| getInt | putInt | Int |
| getBoolean | putBoolean | Boolean |
| getFloat | putFloat | Float |
| getLong | putLong | Long |
| getStringSet | putStringSet | Set<String> |
Editor — το εσωτερικό αντικείμενο του SharedPreferences που συλλέγει αλλαγές σε ένα buffer. Αφού γίνουν όλες οι αλλαγές, ο προγραμματιστής καλεί commit() (σύγχρονη εγγραφή) ή apply() (ασύγχρονη εγγραφή). Η διαφορά είναι κρίσιμη: το commit μπλοκάρει το τρέχον νήμα μέχρι την πλήρη εγγραφή στο δίσκο και επιστρέφει boolean (επιτυχία/αποτυχία), ενώ το apply εκτελεί την εγγραφή σε νήμα παρασκηνίου και επιστρέφει αμέσως τον έλεγχο, αλλά δεν επιστρέφει αποτέλεσμα.
Συνιστάται η χρήση apply αντί commit σε όλες τις περιπτώσεις όπου δεν είναι απαραίτητο να γνωρίζετε το αποτέλεσμα της εγγραφής. Το apply είναι ταχύτερο και δεν μπλοκάρει το νήμα UI. Το commit πρέπει να χρησιμοποιείται μόνο όταν είναι κρίσιμο να γνωρίζετε αν τα δεδομένα αποθηκεύτηκαν επιτυχώς ή κατά την εργασία με λειτουργία multi-process. Για διαγραφή μεμονωμένων κλειδιών χρησιμοποιείται η μέθοδος remove, για πλήρη εκκαθάριση — clear. Όλες οι λειτουργίες διαγραφής εκτελούνται επίσης μέσω του Editor.
// Πολλαπλές αλλαγές - ένα apply
prefs.edit {
putString("theme", "dark")
putBoolean("notifications", false)
remove("old_key")
}
// Ακροατής αλλαγής τιμής
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
Log.d("TAG", "Το κλειδί άλλαξε: $key")
}
Από το Android 12 (API 31), το SharedPreferences έχει συμπληρωθεί με υποστήριξη για registerOnSharedPreferenceChangeListener με αυτόματη απεγγραφή μέσω Lifecycle. Αυτό επιτρέπει την αποφυγή διαρροών μνήμης που σχετίζονται με ξεχασμένους ακροατές. Σε παλαιότερες εκδόσεις, ο προγραμματιστής είναι υποχρεωμένος να καλεί χειροκίνητα το unregisterOnSharedPreferenceChangeListener στο onDestroy ή onStop του στοιχείου.
Παρά την ευρεία διάδοση, το SharedPreferences δεν είναι μια καθολική λύση για όλα τα σενάρια αποθήκευσης δεδομένων στο Android. Ανάλογα με τον όγκο δεδομένων, τις απαιτήσεις ασφάλειας τύπων και απόδοσης, η Google συνιστά διάφορες εναλλακτικές που περιλαμβάνονται στο Android Jetpack και στην τυπική βιβλιοθήκη Android.
| Λύση | Πότε να χρησιμοποιείται | Μειονεκτήματα |
|---|---|---|
| SharedPreferences | Μικρές ρυθμίσεις (έως 100 κλειδιά) | Χωρίς ασφάλεια τύπων, σύγχρονη ανάγνωση |
| DataStore | Ρυθμίσεις μέσης πολυπλοκότητας με coroutines | Χωρίς συμβατότητα προς τα πίσω κάτω από API 14 |
| Room | Δομημένα δεδομένα και λίστες | Υπερβολικό για 3-5 ρυθμίσεις |
| EncryptedSharedPreferences | Ευαίσθητα δεδομένα και διακριτικά | Εξάρτηση από AndroidX Security |
DataStore — μια βιβλιοθήκη Android Jetpack, που παρουσιάστηκε από την Google ως αντικατάσταση του SharedPreferences. Προσφέρει δύο παραλλαγές: Preferences DataStore (κλειδί-τιμή, όπως το SharedPreferences) και Proto DataStore (τυποποιημένη αποθήκευση μέσω Protocol Buffers). Το DataStore χρησιμοποιεί coroutines και Flow για ασύγχρονη εργασία, εγγυάται ασφάλεια τύπων και διαχειρίζεται αυτόματα μεταναστεύσεις εκδόσεων. Η Google συνιστά το DataStore για όλα τα νέα έργα.
Το κύριο πλεονέκτημα του DataStore — ο ασυγχρονισμός σε επίπεδο API. Όλες οι λειτουργίες ανάγνωσης επιστρέφουν Flow, και οι λειτουργίες εγγραφής είναι συναρτήσεις suspend. Αυτό εξαλείφει εντελώς το μπλοκάρισμα του νήματος UI, που είναι δυνατό κατά τη σύγχρονη ανάγνωση SharedPreferences. Επιπλέον, το DataStore εγγυάται τη συνέπεια δεδομένων: η εγγραφή εκτελείται σε μια συναλλαγή και σε περίπτωση αποτυχίας, όλες οι αλλαγές ακυρώνονται.
Ας εξετάσουμε ένα πρακτικό παράδειγμα: ρυθμίσεις θέματος (ανοιχτό/σκοτεινό/σύστημα) σε μια εφαρμογή Android. Ο χρήστης επιλέγει ένα θέμα και η επιλογή αποθηκεύεται στο SharedPreferences. Στις επόμενες εκκινήσεις της εφαρμογής, το θέμα επαναφέρεται από τις αποθηκευμένες ρυθμίσεις. Για αντιδραστική ενημέρωση της διεπαφής χρησιμοποιείται η παρακολούθηση αλλαγών μέσω SharedPreferences.OnSharedPreferenceChangeListener.
Θα δημιουργήσουμε μια κλάση ThemePreferences, η οποία ενσωματώνει όλη την εργασία με το SharedPreferences για το θέμα. Η κλάση παρέχει μεθόδους getTheme (ανάγνωση), setTheme (εγγραφή) και observeTheme (παρακολούθηση). Το όνομα του αρχείου ρυθμίσεων θα είναι "app_preferences" με λειτουργία MODE_PRIVATE. Για ευκολία, τα κλειδιά εξάγονται στο companion object ως σταθερές.
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())
}
}
}
}
Στο Activity ή Fragment, η λήψη της παρουσίας ThemePreferences γίνεται μέσω του πλαισίου της εφαρμογής. Κατά την αρχικοποίηση, καλείται η getTheme για να ορίσει το τρέχον θέμα. Όταν ο χρήστης επιλέγει ένα νέο θέμα, καλείται η setTheme, και μέσω της observeTheme η διεπαφή ενημερώνεται χωρίς επανεκκίνηση του Activity. Είναι σημαντικό να μην ξεχνάτε να απεγγράφεστε από τον ακροατή στο onDestroy για να αποφευχθεί η διαρροή μνήμης, ειδικά αν το Activity αναδημιουργείται κατά την αλλαγή παραμέτρων.
Για εφαρμογές με ελάχιστη έκδοση-στόχο Android 12+, συνιστάται η χρήση registerOnSharedPreferenceChangeListener μαζί με LifecycleObserver. Αυτό διαχειρίζεται αυτόματα την εγγραφή και απεγγραφή κατά την αλλαγή του κύκλου ζωής του στοιχείου. Για παλαιότερες εκδόσεις, η εγγραφή και απεγγραφή πρέπει να γίνονται χειροκίνητα, που αποτελεί συχνή πηγή σφαλμάτων σε εφαρμογές παραγωγής που χρησιμοποιούν SharedPreferences.
Συχνές Ερωτήσεις
SharedPreferences υποστηρίζει άμεσα μόνο πρωτόγονους τύπους και Set<String>. Για την αποθήκευση αντικειμένων, πρέπει να σειριοποιηθούν σε μια συμβολοσειρά JSON μέσω Gson ή Moshi, να αποθηκευτούν μέσω putString και να αποσειριοποιηθούν κατά την ανάγνωση. Για σύνθετα αντικείμενα με πολλά πεδία, συνιστάται η χρήση Room αντί SharedPreferences με σειριοποίηση JSON.
Ναι, το SharedPreferences είναι thread-safe. Όλες οι λειτουργίες ανάγνωσης και εγγραφής συγχρονίζονται σε επίπεδο του αντικειμένου SharedPreferences και του Editor του. Ωστόσο, κατά τη χρήση λειτουργίας multi-process, ο συγχρονισμός δεν είναι εγγυημένος. Για ταυτόχρονη πρόσβαση από πολλαπλά νήματα εντός μιας εφαρμογής, το SharedPreferences είναι ασφαλές χωρίς πρόσθετες κλειδώσεις.
Για πλήρη εκκαθάριση όλων των δεδομένων από το SharedPreferences, καλέστε τη μέθοδο clear() στον Editor και εφαρμόστε τις αλλαγές μέσω apply. Εάν χρειάζεται να διαγράψετε το ίδιο το XML αρχείο, χρησιμοποιήστε deleteSharedPreferences(name) στο πλαίσιο. Η εκκαθάριση δεδομένων εφαρμογής μέσω Ρυθμίσεις → Εφαρμογές → Εκκαθάριση δεδομένων καταργεί επίσης όλα τα αρχεία SharedPreferences.
Για νέα έργα, η Google συνιστά το DataStore ως αντικατάσταση του SharedPreferences. Το DataStore παρέχει ασύγχρονη εργασία με coroutines, ασφάλεια τύπων (Proto DataStore) και αυτόματες μεταναστεύσεις. Το SharedPreferences πρέπει να επιλέγεται μόνο για έργα με ελάχιστη έκδοση κάτω από API 14 ή όταν απαιτείται γρήγορη ενσωμάτωση χωρίς πρόσθετες εξαρτήσεις.
Για κρυπτογράφηση δεδομένων, χρησιμοποιήστε το EncryptedSharedPreferences από τη βιβλιοθήκη AndroidX Security. Κρυπτογραφεί αυτόματα κλειδιά και τιμές με AES-256 GCM. Η διαδικασία ρύθμισης είναι ελάχιστη: το getSharedPreferences αντικαθίσταται από EncryptedSharedPreferences.create με καθορισμό του κύριου κλειδιού από το Android Keystore.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης