← Назад к вопросам

Что такое SharedPreferences и когда его использовать?

1.6 Junior🔥 111 комментариев
#Работа с данными

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое SharedPreferences?

SharedPreferences — это легковесный механизм в Android для хранения простых данных в виде пар ключ-значение (key-value) в формате XML-файла. Этот API является частью Android Framework и предназначен для сохранения примитивных типов данных: String, int, long, float, boolean и Set<String>.

Ключевые характеристики:

  • Хранилище типа ключ-значение — аналогично Map или Properties.
  • Формат хранения — XML-файлы, расположенные в приватной директории приложения (/data/data/<package_name>/shared_prefs/).
  • Потокобезопасность — методы get являются потокобезопасными, но операции записи (apply/commit) должны синхронизироваться.
  • Интерфейсный подход — доступ осуществляется через интерфейс SharedPreferences, реализуемый системой.

Базовое использование:

// Получение экземпляра (по умолчанию — файл "preferences.xml")
val prefs = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)

// Запись данных
prefs.edit()
    .putString("username", "JohnDoe")
    .putInt("user_age", 25)
    .putBoolean("is_premium", true)
    .apply() // Асинхронное сохранение

// Чтение данных
val username = prefs.getString("username", "default")
val age = prefs.getInt("user_age", 0)

Когда использовать SharedPreferences?

✅ Рекомендуемые сценарии:

  1. Настройки пользователя (User Preferences) — сохранение пользовательских предпочтений (тема приложения, язык, единицы измерения).
  2. Флаги состояния приложения — хранение простых состояний типа "первый запуск", "показывать подсказки".
  3. Кэширование легковесных данных — токены авторизации, идентификаторы сессий, временные метки.
  4. Счетчики и статистика — количество запусков приложения, последняя версия обновления.

❌ Когда НЕ следует использовать:

  1. Структурированные или сложные данные — для этого нужны базы данных (Room, SQLite) или файловое хранилище.
  2. Конфиденциальная информация — пароли, PIN-коды должны храниться в EncryptedSharedPreferences или KeyStore.
  3. Большие объемы данных — XML-файлы становятся неэффективными при хранении тысяч записей.
  4. Частые и объемные операции записи — каждый вызов apply()/commit() вызывает парсинг и запись всего файла.

Важные нюансы и лучшие практики:

1. Apply vs Commit

// apply() — асинхронный, безопасный, без возвращаемого значения
prefs.edit().putString("key", "value").apply()

// commit() — синхронный, возвращает boolean успеха, блокирует UI-поток
val success = prefs.edit().putString("key", "value").commit()

Всегда предпочитайте apply(), если не требуется немедленная гарантия записи.

2. Безопасность данных

Начиная с Android 6.0, MODE_WORLD_READABLE и MODE_WORLD_WRITEABLE deprecated. Для конфиденциальных данных используйте:

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. Производительность

  • SharedPreferences не предназначен для высоконагруженных операций.
  • При работе с большими наборами данных используйте getAll() вместо множественных get().
  • Для хранения больших JSON или сложных объектов рассмотрите альтернативы (DataStore, Room).

Альтернативы в современной разработке:

  1. DataStore (Jetpack) — рекомендуется Google как замена SharedPreferences:

    • Preferences DataStore — аналог SharedPreferences с Flow API
    • Proto DataStore — типобезопасное хранение protobuf-объектов
  2. Room — для структурированных данных с SQL-запросами.

Пример миграции на DataStore:

// Создание DataStore
val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings")

// Запись данных
suspend fun saveSettings() {
    dataStore.edit { preferences ->
        preferences[stringPreferencesKey("username")] = "JohnDoe"
        preferences[intPreferencesKey("user_age")] = 25
    }
}

// Чтение данных как Flow
val usernameFlow: Flow<String> = dataStore.data
    .map { prefs -> prefs[stringPreferencesKey("username")] ?: "" }

Заключение

SharedPreferences — это проверенный временем инструмент для хранения простых конфигурационных данных, но с появлением DataStore и требованиями к безопасности его использование следует ограничить легаси-кодом или простейшими сценариями. Для новых проектов рекомендуется использовать DataStore, который предоставляет асинхронный API, типобезопасность и лучшую обработку ошибок. Главное правило: выбирайте инструмент хранения данных в соответствии с конкретными требованиями — нет "серебряной пули" для всех случаев.