DataStore 与 SharedPreferences
了解 DataStore 为什么是现代选择
DataStore 与 SharedPreferences 是 CoddyKit 上的免费 Android Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 4 节课。
存储少量设置
几乎每个应用都需要记住一些少量数据:深色模式开关、上次使用的标签页、用户名等。这些属于键值偏好设置,而不是大型关系型数据。
多年来,Android 一直使用 SharedPreferences 完成这项工作。如今推荐的解决方案是 DataStore。
什么是 SharedPreferences
SharedPreferences 是一种由 XML 支持的简单键值存储。您可以获取编辑器、写入值,然后提交这些值。
- 易于使用
- 内置于框架中
- 同步 API 可能阻塞界面线程
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
prefs.edit().putBoolean("dark_mode", true).apply()
val dark = prefs.getBoolean("dark_mode", false)SharedPreferences 的问题
SharedPreferences 存在一些实际缺陷:
getX()读取操作可能阻塞调用线程(通常是主线程)commit()会同步执行磁盘 I/O- 没有内置的错误通知机制
- API 既不具备类型安全性,也不是响应式的
引入 DataStore
DataStore 是基于 Kotlin 协程和 Flow 构建的现代替代方案。它会在主线程之外执行所有磁盘操作,并将数据公开为可观察流。
DataStore 有两种形式:Preferences DataStore(键值数据)和 Proto DataStore(类型化对象)。
从设计上支持异步
DataStore 永远不会阻塞界面。读取操作通过您收集的 Flow 提供,写入操作则是从协程中调用的 suspend 函数。
这意味着即使在主线程上读取和写入设置也是安全的,因为繁重的工作会在后台调度器上执行。
val darkMode: Flow<Boolean> = dataStore.data
.map { prefs -> prefs[DARK_MODE_KEY] ?: false }响应式更新
由于 DataStore 公开的是 Flow,因此值发生变化时,界面会自动更新。使用 SharedPreferences 时,您必须注册一个繁琐的变更监听器。
在 Jetpack Compose 中,您只需对流调用 collectAsState(),屏幕就会在每次更新时重新组合。
事务性与一致性
DataStore 的写入操作具有事务性。更新要么完全成功,要么完全失败,因此您永远不会读取到只写入了一部分的值。
此外,在同一进程中进行多次读取和写入时,它也能保证数据一致性。
错误处理
SharedPreferences 会悄悄吞掉 I/O 问题。DataStore 会将问题暴露出来:读取操作可能通过流发出 IOException,您可以使用 catch 捕获并进行恢复。
val settings: Flow<Settings> = dataStore.data
.catch { e ->
if (e is IOException) emit(emptyPreferences())
else throw e
}
.map { /* map to your model */ }DataStore 不适用的情况
DataStore 适用于少量或中等规模的键值数据或类型化数据。它不是数据库。
- 大型数据集、查询、关系:使用 Room
- 文件、图片、媒体:使用文件系统
- 少量设置:使用 DataStore
添加依赖
要使用偏好设置 DataStore,请将相应构件添加到模块的 Gradle 文件中。Proto DataStore 使用单独的构件。
dependencies {
implementation("androidx.datastore:datastore-preferences:1.1.1")
}从 SharedPreferences 迁移
您不必一次性重写所有内容。DataStore 提供了 SharedPreferencesMigration,可在首次读取时自动迁移现有值。
val Context.dataStore by preferencesDataStore(
name = "settings",
produceMigrations = { context ->
listOf(SharedPreferencesMigration(context, "settings"))
}
)快速检查
请检验您对为何首选 DataStore 的理解。
回顾
您已经了解了为何 DataStore 是键值设置的现代选择:
- SharedPreferences 可能阻塞主线程,并且不是响应式的
- DataStore 使用协程和
Flow实现安全的异步访问 - 写入具有事务性,并配有适当的错误处理
- 有两种形式:偏好设置和 Proto
接下来,您将在实践中使用 preferencesDataStore 委托。
常见问题解答
「DataStore 与 SharedPreferences」课时是免费的吗?
是的 — 「DataStore 与 SharedPreferences」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 4 节课。
「DataStore 与 SharedPreferences」这节课中我会学到什么?
了解 DataStore 为什么是现代选择 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Android Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「DataStore 与 SharedPreferences」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Android Academy 课中编写并运行代码吗?
能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- DataStore 与 SharedPreferences
- Preferences DataStore
- 读取和写入设置
- Proto DataStore