Skip to main content

Working with SharedPreferences

1. Getting SharedPreferences Instance

Method Description Return Type Notes
getSharedPreferences(String name, int mode) Retrieves a SharedPreferences instance for a specific shared preferences file SharedPreferences Creates the file if it does not exist
getSharedPreferences(int resId, int mode) Retrieves a SharedPreferences instance using a resource ID SharedPreferences Useful for centralized preference management

Example: Getting SharedPreferences Instance

val prefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE)
val prefsFromRes = context.getSharedPreferences(R.xml.preferences, Context.MODE_PRIVATE)
Note: The mode parameter controls file access permissions. Common values are Context.MODE_PRIVATE, Context.MODE_WORLD_READABLE, and Context.MODE_WORLD_WRITEABLE.

2. Storing Primitives

Primitive Type Method Description
Boolean edit().putBoolean(key, value) Stores a boolean value
Integer edit().putInt(key, value) Stores an integer value
Long edit().putLong(key, value) Stores a long value
Float edit().putFloat(key, value) Stores a float value
String edit().putString(key, value) Stores a string value

Example: Storing and Retrieving Boolean

val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val editor = prefs.edit()
editor.putBoolean("isDarkMode", true)
editor.apply()

val isDarkMode = prefs.getBoolean("isDarkMode", false)

Example: Storing and Retrieving Integer

val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val editor = prefs.edit()
editor.putInt("userAge", 25)
editor.apply()

val userAge = prefs.getInt("userAge", 0)

3. Retrieving Values

Method Description Return Type Notes
getString(key, defaultValue) Retrieves a String value from SharedPreferences String? Use null as default if no value exists
getInt(key, defaultValue) Retrieves an Int value from SharedPreferences Int Default value is returned if key does not exist
getBoolean(key, defaultValue) Retrieves a Boolean value from SharedPreferences Boolean Default value is returned if key does not exist
getFloat(key, defaultValue) Retrieves a Float value from SharedPreferences Float Default value is returned if key does not exist
getLong(key, defaultValue) Retrieves a Long value from SharedPreferences Long Default value is returned if key does not exist
getStringSet(key, defaultValue) Retrieves a Set<String> value from SharedPreferences Set<String>? Use null as default if no value exists

Example: Retrieving Values

val prefs = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val username = prefs.getString("username", "defaultUser")
val userAge = prefs.getInt("age", 0)
val isPremium = prefs.getBoolean("isPremium", false)
val theme = prefs.getStringSet("themes", setOf("light"))
Note: If a key does not exist, the default value is returned. Always ensure that your default values make sense for the expected data type.

4. Using Preferences Editor

Example: Saving and Editing Preferences

val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val editor = prefs.edit()
editor.putString("username", "john_doe")
editor.putInt("user_id", 12345)
editor.putBoolean("is_logged_in", true)
editor.apply()
Method Description Notes
putString(key, value) Stores a string value Key must be unique
putInt(key, value) Stores an integer value
putBoolean(key, value) Stores a boolean value
putFloat(key, value) Stores a float value
putLong(key, value) Stores a long value
putStringSet(key, value) Stores a set of strings Available from API 11
remove(key) Removes a key-value pair
clear() Removes all key-value pairs
apply() Asynchronously saves changes Recommended over commit()
commit() Synchronously saves changes Returns boolean success status
Note: apply() is preferred over commit() for better performance as it runs asynchronously.

5. Removing Data

SharedPreferences allows you to remove specific keys or clear all data using the edit() method.

Action Description Code Example
remove(key) Removes the key-value pair associated with the specified key.
val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
prefs.edit().remove("username").apply()
clear() Removes all key-value pairs from the SharedPreferences.
val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
prefs.edit().clear().apply()
Note: Changes made using edit() must be committed with either apply() or commit(). apply() is asynchronous and preferred for performance.

6. Implementing OnSharedPreferenceChangeListener

Use OnSharedPreferenceChangeListener to observe changes to SharedPreferences values in real time.

Example: Registering a Listener

val prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val listener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
    when (key) {
        "theme" -> {
            val theme = sharedPreferences.getString("theme", "light")
            // Update UI based on theme change
        }
        "notifications" -> {
            val enabled = sharedPreferences.getBoolean("notifications", true)
            // Toggle notification behavior
        }
    }
}
prefs.registerOnSharedPreferenceChangeListener(listener)

Example: Unregistering a Listener

prefs.unregisterOnSharedPreferenceChangeListener(listener)
Method Description Notes
registerOnSharedPreferenceChangeListener() Registers a listener for preference changes Must be called on the main thread
unregisterOnSharedPreferenceChangeListener() Unregisters a previously registered listener Prevents memory leaks if not unregistered
Note: The listener is called on the main thread, so avoid heavy operations inside it.
Warning: If the listener is not unregistered, it can cause memory leaks or unexpected behavior.

7. Using Encrypted SharedPreferences

Feature Description Notes
EncryptedSharedPreferences EncryptedSharedPreferences provides secure storage for key-value pairs using AES-256 encryption. Available in Android Security Library
Master Key Uses a master key derived from Android Keystore for encryption. Automatically managed by the library

Example: Creating EncryptedSharedPreferences

import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

val sharedPreferences = EncryptedSharedPreferences.create(
    "encrypted_preferences",
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_GCM,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

Example: Storing and Retrieving Data

val editor = sharedPreferences.edit()
editor.putString("username", "user123")
editor.apply()

val username = sharedPreferences.getString("username", "")
Note: EncryptedSharedPreferences is not suitable for storing large amounts of data due to encryption overhead.

8. Applying Best Practices

Best Practices for SharedPreferences

  • Use apply() for asynchronous saving to avoid blocking the main thread
  • Use commit() only when synchronous behavior is required (e.g., before app exit)
  • Store only primitive data types and small amounts of data (avoid large objects or JSON)
  • Use SharedPreferences for simple key-value storage, not complex data structures
  • Prefer Context.MODE_PRIVATE to restrict access to the app only
  • Use Editor with apply() in a single transaction to improve performance
  • Avoid storing sensitive data (e.g., passwords) in SharedPreferences
  • Use apply() with runBlocking or similar for coroutine-based async operations
Method Description Usage Notes
apply() Asynchronously saves changes to disk editor.apply() Non-blocking, preferred for most use cases
commit() Synchronously saves changes to disk editor.commit() Blocking, returns boolean indicating success
getString() Retrieves a string value prefs.getString("key", "default") Use default value for safety
getInt() Retrieves an integer value prefs.getInt("key", 0) Use default value for safety
getBoolean() Retrieves a boolean value prefs.getBoolean("key", false) Use default value for safety

Example: Saving and Retrieving Data

val prefs = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
val editor = prefs.edit()

// Saving data
editor.putString("username", "john_doe")
editor.putBoolean("is_logged_in", true)
editor.apply()

// Retrieving data
val username = prefs.getString("username", "")
val isLoggedIn = prefs.getBoolean("is_logged_in", false)
Warning: SharedPreferences is not suitable for storing large or sensitive data. Use EncryptedSharedPreferences for sensitive values.
Note: SharedPreferences is not thread-safe. If multiple threads access it, use synchronized or Handler to prevent race conditions.

9. Storing Collections

Note: SharedPreferences does not natively support storing collections like ArrayList or Set. You must serialize them to a string format before storing.
Collection Type Storage Method Code Example Notes
List<String> Convert to Set<String>
val list = listOf("item1", "item2", "item3")
val set = list.toSet()
sharedPreferences.edit().putStringSet("myList", set).apply()
Use putStringSet for lists of strings
List<Int> Serialize to JSON or comma-separated string
val list = listOf(1, 2, 3)
val json = Gson().toJson(list)
sharedPreferences.edit().putString("intList", json).apply()
Requires external library like Gson or Moshi
Set<String> Use putStringSet
val set = setOf("a", "b", "c")
sharedPreferences.edit().putStringSet("mySet", set).apply()
Native support in SharedPreferences

Example: Storing and Retrieving a List of Integers

import com.google.gson.Gson

val gson = Gson()
val intList = listOf(10, 20, 30)

// Store
val json = gson.toJson(intList)
sharedPreferences.edit().putString("integers", json).apply()

// Retrieve
val retrievedJson = sharedPreferences.getString("integers", null)
val retrievedList = if (retrievedJson != null) gson.fromJson(retrievedJson, List::class.java) else emptyList()
Note: When storing collections, always consider the size limits of SharedPreferences. Large collections may cause performance issues or exceed storage limits.

10. Migrating to DataStore

SharedPreferences vs DataStore

  • SharedPreferences: Legacy, synchronous, stored in XML files
  • DataStore: Modern, asynchronous, stored in SQLite or ProtoBuf
Feature SharedPreferences DataStore
Storage Format XML SQLite or ProtoBuf
Read/Write Mode Synchronous Asynchronous
Type Safety Not type-safe Type-safe
Thread Safety Not thread-safe Thread-safe
Data Observability No built-in observability Supports Flow for observing changes

Example: Migrating from SharedPreferences to DataStore

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.*

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

// SharedPreferences usage (legacy)
val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
val value = prefs.getString("key", "default")

// DataStore usage (modern)
val valueFlow: Flow<String> = dataStore.data
    .map { preferences ->
        preferences[STRING_PREFERENCES_KEY] ?: "default"
    }
Note: DataStore is the recommended approach for modern Android development due to its asynchronous nature and type safety.

Was this article helpful?