IO — Ivan Labs

Room против SharedPreferences против DataStore: какое хранилище для чего

3 мин чтения
Android

Эти три сравнивают так, будто вы выбираете один для всего приложения. На практике они решают разные проблемы и часто сосуществуют.

SharedPreferences: старое значение по умолчанию, постепенно уходящее

Простое хранилище ключ-значение, исторически значение по умолчанию для небольших настроек. Известные ограничения: его легко неправильно использовать с синхронным чтением в главном потоке (вызывая подёргивания), не предлагает безопасность типов на этапе компиляции, и Google теперь рекомендует DataStore как его замену для нового кода.

DataStore: современная замена для простых данных ключ-значение

DataStore выпускается в двух вариантах — Preferences DataStore (похожая форма на SharedPreferences, но асинхронная и безопаснее) и Proto DataStore (полностью типизированная, использующая protocol buffers). В любом случае, он построен для той же задачи, что делал SharedPreferences — простые настройки и флаги — сделано правильно: асинхронно по умолчанию, с определённой моделью согласованности данных.

val Context.dataStore by preferencesDataStore(name = "settings")
 
val THEME_KEY = stringPreferencesKey("theme")
 
suspend fun saveTheme(context: Context, theme: String) {
    context.dataStore.edit { prefs -> prefs[THEME_KEY] = theme }
}

Room: для реально структурированных, запрашиваемых данных

Room — это полная абстракция SQLite — слой в стиле ORM для структурированных данных с отношениями, запросами и (через coroutines/Flow) реактивными обновлениями. Это правильный инструмент, когда у вас есть подлинная коллекция структурированных записей: список сохранённых элементов, кэшированные результаты API, всё, что вы бы естественно описали как таблицу со строками.

@Entity
data class Note(@PrimaryKey val id: Int, val title: String, val body: String)
 
@Dao
interface NoteDao {
    @Query("SELECT * FROM Note ORDER BY id DESC")
    fun getAll(): Flow<List<Note>>
}

Сравнительная таблица

SharedPreferencesDataStoreRoom
Лучше всего дляУстаревшего кода (избегайте для нового)Простых настроек/флаговСтруктурированных, запрашиваемых данных
Безопасность типовНетСтрогая (особенно Proto DataStore)Строгая
Асинхронность по умолчаниюНет (частый источник багов)ДаДа (с coroutines/Flow)
Обрабатывает отношения/запросыНетНетДа
Текущая рекомендация GoogleПостепенно уходитДа, для данных ключ-значениеДа, для структурированных данных

Практическое правило

Если это горстка флагов или предпочтений (тема, был ли показан онбординг, переключатель уведомлений), используйте DataStore. Если это подлинная коллекция структурированных записей, которую вы бы запрашивали, фильтровали или связывали с другими данными, используйте Room. Избегайте начинать новый код с SharedPreferences — стоимость миграции на DataStore позже можно избежать, просто начав оттуда.

Это решение напрямую связано с более широким вопросом архитектуры — см. наше руководство по проектированию Android-архитектуры, избегающей переписываний, о том, как выборы слоя данных вписываются в общую картину.

Частые вопросы

Устарел ли SharedPreferences?

Формально не удалён, но Google рекомендует DataStore как его замену для нового кода — у SharedPreferences есть известные проблемы (синхронный API в главном потоке, отсутствие строгой типизации), которые DataStore был построен решить специально.

Могу ли я использовать больше одного из них в одном приложении?

Да, и это распространено — Room для структурированных данных (список элементов, записи пользователей), DataStore для простых настроек приложения, используются вместе, а не как конкурирующие варианты для одной задачи.

Нужен ли мне Room для простого экрана настроек?

Нет — Room построен для структурированных, запрашиваемых данных с отношениями. Горстка пользовательских предпочтений (выбор темы, переключатель уведомлений) — именно то, для чего вместо этого предназначен DataStore.

Нужна помощь с этим?

Свяжитесь со мной, и я помогу разобраться.

Связаться со мной

Похожие статьи

Поделиться:X / TwitterLinkedIn