Что такое SharedPreferences?android-60

SharedPreferences — это механизм в Android для хранения простых данных в формате ключ-значение. Это легковесное решение для сохранения примитивных типов данных (boolean, float, int, long, string) и их наборов.

Основные характеристики

  1. Типы хранимых данных:

    • Примитивы: Int, Float, Boolean, Long, String
    • Множества: Set<String>
  2. Формат хранения:

    • XML-файлы в папке приложения (/data/data/ваш.package/shared_prefs/)
    • Пример содержимого файла:
    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <map>
        <boolean name="is_dark_mode" value="true" />
        <string name="username">JohnDoe</string>
    </map>
    
  3. Режимы работы (до API 23):

    • MODE_PRIVATE — доступ только для вашего приложения
    • Устаревшие: MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE

Как использовать?

1. Получение экземпляра

// Предпочтительный способ (с Context)
val prefs = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)

// Для Activity (упрощенный вариант)
val activityPrefs = getPreferences(Context.MODE_PRIVATE)

2. Запись данных

Используйте Editor для модификации:

prefs.edit().apply {
    putBoolean("is_first_launch", false)
    putString("user_email", "user@example.com")
    apply() // или commit()
}

Разница между apply() и commit():

  • apply() — асинхронная запись (без возврата результата)
  • commit() — синхронная запись (возвращает boolean)

3. Чтение данных

val isDarkMode = prefs.getBoolean("is_dark_mode", false) // false - значение по умолчанию
val username = prefs.getString("username", null)

Современные лучшие практики

  1. Инкапсуляция доступа: Создайте отдельный класс-менеджер:

    class PrefsManager(context: Context) {
        private val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
    
        var isFirstLaunch: Boolean
            get() = prefs.getBoolean("is_first_launch", true)
            set(value) = prefs.edit().putBoolean("is_first_launch", value).apply()
    }
    
  2. Безопасность:

    • Для чувствительных данных используйте EncryptedSharedPreferences:
    val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()
    
    val securePrefs = EncryptedSharedPreferences.create(
        context,
        "secure_prefs",
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
    
  3. Миграция на DataStore: Для сложных случаев рекомендуется использовать Jetpack DataStore:

    // В build.gradle:
    implementation "androidx.datastore:datastore-preferences:1.0.0"
    
    // Создание:
    val Context.dataStore by preferencesDataStore(name = "settings")
    

Ограничения SharedPreferences

  1. Не подходит для:

    • Больших объемов данных
    • Сложных структур (используйте Room)
    • Частых обновлений (нет транзакций)
  2. Проблемы производительности:

    • Блокировка UI при commit()
    • Весь файл перезаписывается при изменениях

Резюмируем

  1. Что это: Легковесное хранилище ключ-значение в XML
  2. Когда использовать:
    • Настройки пользователя
    • Флаги состояния приложения
    • Небольшие простые данные
  3. Лучшие практики:
    • Инкапсулируйте логику
    • Используйте apply() вместо commit()
    • Для чувствительных данных — шифрование
  4. Альтернативы:
    • EncryptedSharedPreferences для безопасности
    • DataStore для современного подхода

Пример использования с LiveData:

fun getLivePreference(key: String, defValue: T): LiveData<T> {
    return prefs.liveData(key, defValue) // Используя androidx.lifecycle:lifecycle-livedata-ktx
}