| 分类 android  | 标签 DataStore  Preferences  数据存储  Android  Jetpack 

title

引言

DataStore 是 Android 推荐的替代 SharedPreferences 的现代数据存储解决方案,于 2020 年发布。SharedPreferences 存在同步 I/O 阻塞主线程、无类型安全、缺乏事务支持等问题。DataStore 基于 Kotlin 协程和 Flow,提供类型安全、事务性 API,并且完全异步,不会阻塞主线程。DataStore 分为 Preferences DataStore(类似 SharedPreferences 的键值对)和 Proto DataStore(基于 Protocol Buffers 的强类型存储)。本文将深入探讨 DataStore Preferences 的使用方式、迁移策略以及最佳实践。

为什么迁移到 DataStore

SharedPreferences 的 getStringcommit 等可能触发磁盘 I/O,在主线程调用会卡顿。DataStore 的读写都是挂起函数,需在协程中调用,天然避免主线程阻塞。DataStore 支持事务:edit 块内的多次修改要么全部成功,要么全部回滚。Preferences DataStore 使用类型化的 Key(如 intPreferencesKey),避免键名拼写错误和类型转换异常。Google 已明确推荐新项目使用 DataStore,SharedPreferences 将逐步被取代。

添加依赖

dependencies {
    implementation("androidx.datastore:datastore-preferences:1.0.0")
    // 或使用 Proto DataStore
    implementation("androidx.datastore:datastore:1.0.0")
}

Preferences DataStore

通过 preferencesDataStore 委托创建 DataStore 实例,name 指定文件名(不含路径)。Key 使用 booleanPreferencesKeystringPreferencesKeyintPreferencesKey 等创建,保证类型安全。data 属性是 Flow,可多次收集,每次数据变化会发射新值。edit 是挂起函数,在块内通过 preferences[key] = value 修改,块结束时自动提交。

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

// 写入数据
suspend fun saveTheme(isDark: Boolean) {
    context.dataStore.edit { preferences ->
        preferences[PreferencesKeys.BOOLEAN_KEY] = isDark
    }
}

// 读取数据
val themeFlow: Flow<Boolean> = context.dataStore.data
    .map { preferences ->
        preferences[PreferencesKeys.BOOLEAN_KEY] ?: false
    }

// 定义 Key
object PreferencesKeys {
    val BOOLEAN_KEY = booleanPreferencesKey("theme_dark")
    val STRING_KEY = stringPreferencesKey("user_name")
    val INT_KEY = intPreferencesKey("user_age")
}

在 ViewModel 中使用

ViewModel 通过构造函数注入 DataStore,或从 Application 的 dataStore 获取。将 data 的 Flow 通过 map 转换为业务需要的类型,在 UI 层收集并更新界面。写入时在 viewModelScope.launch 中调用 edit。注意:DataStore 的 data Flow 是热流,多次收集会多次读取;若需共享,可在 Repository 层缓存或使用 stateIn

class SettingsViewModel(private val dataStore: DataStore<Preferences>) : ViewModel() {
    
    val theme: Flow<Boolean> = dataStore.data
        .map { it[PreferencesKeys.BOOLEAN_KEY] ?: false }
    
    fun setTheme(isDark: Boolean) {
        viewModelScope.launch {
            dataStore.edit { it[PreferencesKeys.BOOLEAN_KEY] = isDark }
        }
    }
}

迁移 SharedPreferences

DataStore 提供 SharedPreferencesMigration,可在首次访问时从 SharedPreferences 读取数据并写入 DataStore,然后删除旧文件。在 preferencesDataStoreproduceMigrations 参数中提供 migration 列表。迁移在 DataStore 初始化时执行,会阻塞直到完成,因此迁移逻辑应尽快完成,避免复杂计算。

val dataStore = PreferenceDataStoreFactory.create(
    migrations = { context, _ ->
        context.getSharedPreferences("old_prefs", Context.MODE_PRIVATE)
    }
) {
    context.dataStore
}

总结

DataStore 提供了更安全、更现代的数据存储方式,是 SharedPreferences 的推荐替代方案。掌握 Preferences API、Flow 收集和迁移策略,可以平滑迁移现有项目,并享受类型安全和异步 I/O 带来的好处。


上一篇     下一篇