1. SharedPreferences的问题
1. 卡顿: 读写数据的时候,可能会阻塞UI线程,导致页面卡死
2. 不安全: 解析错误的时候,会直接抛出异常,导致程序崩溃
3. 没法监听: 想在数据变化时自动更新页面,SP做起来会很麻烦
2. DataStore的优势
1. 基于协程和Flow: 完全异步,不卡顿
2. 一致性保证:保证数据读写的原子性(要么成功,要么失败,不会出现数据错乱)
3. 错误处理:内置了完善的异常处理机制
3. DataStore的两种类型
DataStore提供了两种不同的实现,就像选工具箱:
-
Preferences DataStore- 特点:像
Map一样通过键值对存储 - 适合场景:保存简单的数据,如布尔值、整型、字符串
- 难度:入门级,最常用
- 特点:像
Proto DataStore
暂时不讲
4. 如何在项目中使用
1. 添加依赖
implementation "androidx.datastore:datastore-preferences:1.2.1"
2. 创建 DataStore 实例
// 定义在文件的顶层(Class外面)
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "ble_saved_devices")
3. 定义Key
// 你需要告诉DataStore,你要存的数据叫什么名字,是什么类型
private val KEY_HSRC = stringPreferencesKey("slot_hsrc_device")
private val KEY_SPO2 = stringPreferencesKey("slot_spo2_device")
4. 写入数据
// DataStore 必须在协程中操作。我们使用.edit方法
suspend fun saveDevice(name: String, address: String) {
val context = getContext()
context.dataStore.edit { preferences ->
when(type) {
DeviceType.HSRC -> preferences[KEY_HSRC] = value
DeviceType.SPO2 -> preferences[KEY_SPO2] = value
}
}
}
5. 读取数据
// DataStore返回的是一个Flow,这意味着,一旦数据变了,UI会自动收到通知
val hsrcDeviceFlow: Flow<SavedBleDevice?>
get() {
val context = getContext()
return context.dataStore.data.map { preferences ->
val value = preferences[KEY_HSRC] ?: return@map null
parseDevice(value, DeviceType.HSRC)
}
}
6. 在ViewModel里面
val hsrcDeviceFlow: StateFlow<SavedBleDevice?> = BleDeviceRepository.hsrcDeviceFlow
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = null
)
7. 在Activity里面
lifecycleScope.launch {
// 1. 监听头盒设备是否存在
viewModel?.hsrcDeviceFlow?.collect { device ->
}
}