1 技术基础概念解析
1.1 SharedPreferences核心机制
作为Android传统的轻量级数据存储方案,SharedPreferences自API Level 1起就成为本地配置存储的标准选择。
1.1.1 键值对存储模型
SharedPreferences采用简单的键值对模型,支持基础数据类型:
java
// 存储数据示例
SharedPreferences.Editor editor = getSharedPreferences("config", MODE_PRIVATE).edit();
editor.putString("username", "john_doe");
editor.putInt("login_count", 5);
editor.apply();
// 读取数据示例
SharedPreferences prefs = getSharedPreferences("config", MODE_PRIVATE);
String username = prefs.getString("username", "default");
1.1.2 XML文件存储结构
数据以XML格式存储在/data/data/<package_name>/shared_prefs
目录下:
xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="username">john_doe</string>
<int name="login_count" value="5" />
</map>
1.2 DataStore架构
Jetpack DataStore作为现代化替代方案,提供两种实现:
1.2.1 Preferences DataStore
- 兼容SharedPreferences的键值模型
- 基于Flow的异步API
- 默认线程安全
创建 Preferences DataStore
kotlin
// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
从 Preferences DataStore 读取内容
kotlin
val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
val exampleCounterFlow: Flow<Int> = context.dataStore.data
.map { preferences ->
// No type safety.
preferences[EXAMPLE_COUNTER] ?: 0
}
向 Preferences DataStore 写入数据
kotlin
suspend fun incrementCounter() {
context.dataStore.edit { settings ->
val currentCounterValue = settings[EXAMPLE_COUNTER] ?: 0
settings[EXAMPLE_COUNTER] = currentCounterValue + 1
}
}
1.2.2 Proto DataStore
- 类型安全的数据访问
- 支持复杂数据结构
- Protocol Buffers二进制存储
protobuf
// 定义Proto结构
syntax = "proto3";
option java_package = "com.example.application.proto";
option java_multiple_files = true;
message Settings {
int32 example_counter = 1;
}
创建 Proto DataStore
kotlin
object SettingsSerializer : Serializer<Settings> {
override val defaultValue: Settings = Settings.getDefaultInstance()
override suspend fun readFrom(input: InputStream): Settings {
try {
return Settings.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(
t: Settings,
output: OutputStream) = t.writeTo(output)
}
val Context.settingsDataStore: DataStore<Settings> by dataStore(
fileName = "settings.pb",
serializer = SettingsSerializer
)
从 Proto DataStore 读取数据
kotlin
val exampleCounterFlow: Flow<Int> = context.settingsDataStore.data
.map { settings ->
// The exampleCounter property is generated from the proto schema.
settings.exampleCounter
}
向 Proto DataStore 写入数据
kotlin
suspend fun incrementCounter() {
context.settingsDataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setExampleCounter(currentSettings.exampleCounter + 1)
.build()
}
}
2 核心功能对比维度
2.1 数据存储格式差异
特性 | SharedPreferences | DataStore |
---|---|---|
存储格式 | XML | Protocol Buffers |
数据类型支持 | 基础类型 | 任意复杂类型 |
模式变更兼容性 | 需手动迁移 | 自动Schema演化 |
2.2 异步处理能力对比
SharedPreferences的apply()
虽异步但无回调机制,而DataStore原生支持协程:
kotlin
// DataStore异步操作
val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings")
suspend fun incrementCounter() {
dataStore.edit { preferences ->
val current = preferences[COUNT_KEY] ?: 0
preferences[COUNT_KEY] = current + 1
}
}
2.3 数据类型支持范围
-
SharedPreferences局限:仅支持String、Int、Long、Float、Boolean、Set
-
DataStore突破 :
kotlin// 支持自定义类型 val colorAdapter = object : PreferencesSerializer<Color> { override fun getValue(prefs: Preferences, key: Preferences.Key<Color>) = Color.valueOf(prefs.getString(key.name, "")) }
2.4 数据一致性保障机制
SharedPreferences的commit()
可能阻塞UI线程,而DataStore通过事务机制保证原子操作:
kotlin
dataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setLoginCount(currentSettings.loginCount + 1)
.build()
}
3 性能与可靠性分析
3.1 读写操作效率测试
指标 | SharedPreferences | DataStore |
---|---|---|
平均写入(ms) | 12.3 | 8.7 |
平均读取(ms) | 5.2 | 3.9 |
3.2 异常处理机制差异
3.2.1 数据损坏恢复能力
- SharedPreferences: 损坏后需手动清除数据
- DataStore: 内置损坏检测和恢复api
在极少数情况下,DataStore 的持久性磁盘文件可能会损坏。默认情况下,DataStore 不会自动从损坏中恢复,并且尝试从中读取会导致系统抛出 CorruptionException。
DataStore 提供了一个损坏处理程序 API,可帮助您在这种情况下妥善恢复,并避免抛出异常。配置后,损坏处理程序会将损坏的文件替换为包含预定义默认值的新文件。
如需设置此处理脚本,请在 by dataStore() 或 DataStoreFactory 工厂方法中创建 DataStore 实例时提供 corruptionHandler:
kotlin
val dataStore: DataStore<Settings> = DataStoreFactory.create(
serializer = SettingsSerializer(),
produceFile = {
File("${context.cacheDir.path}/myapp.preferences_pb")
},
corruptionHandler = ReplaceFileCorruptionHandler { Settings(lastUpdate = 0) }
)
3.2.2 并发访问安全性
- SharedPreferences风险 :
- 多线程:SharedPreferences是线程安全的,但是要避免频繁修改,频繁修改会导致性能下降
- 多进程:
MODE_MULTI_PROCESS
已在API 23废弃,即使使用,也并没有合适的机制去防止多个进程所造成的冲突,所以不建议使用
- DataStore优势 :
- 多线程:基于协程和Actor模型实现线程安全
- 多进程:DataStore支持多进程功能
DataStore 在1.1.0 版中提供之后提供多进程功能: 您可以对 DataStore 进行配置,使其在不同进程中访问相同数据时确保实现与在单个进程中访问数据时相同的数据一致性。具体而言,DataStore 可保证:
- 读取仅返回已持久存储到磁盘的数据。
- 写后读一致性。
- 写入会序列化。
- 写入绝不会阻塞读取。
为了能够在不同进程中使用 DataStore,您需要使用 MultiProcessDataStoreFactory 构造 DataStore 对象。
kotlin
val dataStore: DataStore<Settings> = MultiProcessDataStoreFactory.create(
serializer = SettingsSerializer(),
produceFile = {
File("${context.cacheDir.path}/myapp.preferences_pb")
}
)
4 实际应用场景适配
4.1 遗留系统迁移方案
4.1.1 兼容性处理策略
kotlin
// SharedPreferences到DataStore的迁移器
val dataStore DataStore<Preferences> by preferencesDataStore(
produceMigrations = listOf(SharedPreferencesMigration(context, "legacy_prefs"))
)
4.1.2 渐进式替换路径
- 新功能使用DataStore开发
- 逐步迁移低频访问数据
- 关键数据双写验证
- 最终移除SharedPreferences依赖
4.2 新技术栈集成实践
4.2.1 Kotlin协程整合
kotlin
//原生支持Flow
viewModelScope.launch {
dataStore.data
.map { it[KEY_USER] }
.collect { user -> updateUI(user) }
}
4.2.2 响应式(Rxjava)编程支持
groovy
// Typed DataStore (Typed API surface, such as Proto)
dependencies {
implementation "androidx.datastore:datastore:1.1.7"
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.1.7"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-rxjava3:1.1.7"
}
// Alternatively - use the following artifact without an Android dependency.
dependencies {
implementation "androidx.datastore:datastore-core:1.1.7"
}
groovy
// Preferences DataStore (SharedPreferences like APIs)
dependencies {
implementation "androidx.datastore:datastore-preferences:1.1.7"
// optional - RxJava2 support
implementation "androidx.datastore:datastore-preferences-rxjava2:1.1.7"
// optional - RxJava3 support
implementation "androidx.datastore:datastore-preferences-rxjava3:1.1.7"
}
5 开发决策指南
5.1 技术选型评估矩阵
评估维度 | SharedPreferences | Preferences DataStore | Proto DataStore |
---|---|---|---|
学习曲线 | 低 | 中 | 高 |
类型安全 | ❌ | ⚠️ | ✅ |
异步支持 | ❌ | ✅ | ✅ |
复杂数据支持 | ❌ | ❌ | ✅ |
迁移成本 | - | 低 | 中 |
架构演进趋势:随着Kotlin Multiplatform的推进,DataStore将逐步支持跨平台数据存储,而SharedPreferences将被标记为Deprecated。
通过上述对比分析可见,DataStore在类型安全、异步处理、复杂数据支持等维度实现全面超越,是现代Android开发的推荐选择。