当前位置: 首页 > news >正文

Compose笔记(十一)--DataStore(二)

         这一节主要了解一下DataStore的源码,datastore-preferences 基于 Flow 和 Coroutines 实现异步数据存储。它的核心原理是将键值对数据存储在一个文件中,通过文件读写操作实现数据的持久化。在读取数据时,会将文件内容解析为键值对;在写入数据时,会将新的键值对更新到文件中。为了保证数据的一致性和并发安全性,使用了锁机制和事务处理。

1 创建 DataStore 实例
       当你通过 preferencesDataStore 扩展函数创建 DataStore 实例时,实际上是调用了 DataStoreFactory 的 create 方法。

val Context.dataStore by preferencesDataStore(name = "my_preferences")

preferencesDataStore 扩展函数的实现如下:

fun Context.preferencesDataStore(
    name: String,
    corruptionHandler: PreferencesDataCorruptionHandler? = null,
    migrations: List<DataMigration<Preferences>> = emptyList(),
    scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
): DataStore<Preferences> = DataStoreFactory.create(
    serializer = PreferencesSerializer,
    produceFile = { getPreferencesDataStoreFile(name) },
    corruptionHandler = corruptionHandler,
    migrations = migrations,
    scope = scope
)

serializer:指定数据的序列化器,PreferencesSerializer 负责将 Preferences 对象序列化为字节流和从字节流反序列化为 Preferences 对象。
produceFile:返回存储数据的文件。
corruptionHandler:处理数据损坏的回调。
migrations:数据迁移策略列表。
scope:协程作用域,用于执行异步操作。

2. 读取数据
当调用 dataStore.data 获取 Flow<Preferences> 时,会触发数据的读取操作。

val preferencesFlow: Flow<Preferences> = dataStore.data

DataStore 接口的 data 属性实现如下:

override val data: Flow<Preferences> = flow {
    while (true) {
        val data = readData()
        emit(data)
        // 监听文件变化
        val changeFlow = watchForFileChanges()
        changeFlow.collect {
            // 文件变化时重新读取数据
            val newData = readData()
            emit(newData)
        }
    }
}

readData:从文件中读取数据并解析为 Preferences 对象。
watchForFileChanges:监听文件变化,当文件发生变化时会触发重新读取数据。

3. 写入数据
当调用 dataStore.edit 方法时,会开始一个事务来更新数据。

suspend fun writeData() {
    dataStore.edit { preferences ->
        preferences[PreferencesKeys.KEY_NAME] = "value"
    }
}

edit 方法的实现如下:

override suspend fun edit(transform: suspend (Preferences) -> Preferences): Preferences {
    return transaction { currentPreferences ->
        val newPreferences = transform(currentPreferences)
        writeData(newPreferences)
        newPreferences
    }
}

transaction:开启一个事务,确保数据的一致性和并发安全性。
transform:用户提供的转换函数,用于更新 Preferences 对象。
writeData:将更新后的 Preferences 对象写入文件。

4. 序列化和反序列化
PreferencesSerializer 负责 Preferences 对象的序列化和反序列化。

object PreferencesSerializer : Serializer<Preferences> {
    override val defaultValue: Preferences = Preferences.Empty

    override suspend fun readFrom(input: InputStream): Preferences {
        return try {
            val byteArray = input.readBytes()
            Preferences(ByteArrayPreferencesMap(byteArray))
        } catch (e: IOException) {
            defaultValue
        }
    }

    override suspend fun writeTo(t: Preferences, output: OutputStream) {
        val byteArray = (t.map as ByteArrayPreferencesMap).toByteArray()
        output.write(byteArray)
    }
}

readFrom:从输入流中读取字节数组,并将其解析为 Preferences 对象。
writeTo:将 Preferences 对象转换为字节数组,并写入输出流。

并发控制和数据一致性
datastore-preferences 使用锁机制和事务处理来保证并发控制和数据一致性。在 transaction 方法中,会使用一个锁来确保同一时间只有一个事务可以修改数据。

private suspend fun <T> transaction(transform: suspend (Preferences) -> T): T {
    return withContext(scope.coroutineContext) {
        lock.withLock {
            val currentPreferences = readData()
            val result = transform(currentPreferences)
            writeData(currentPreferences)
            result
        }
    }
}

简单总结,datastore-preferences 的源码流程主要包括创建 DataStore 实例、读取数据、写入数据和序列化反序列化。通过 Flow 和 Coroutines 实现异步操作,使用锁机制和事务处理保证并发控制和数据一致性。这种设计使得数据存储更加安全、高效和可靠。

相关文章:

  • Day09 -实例:拿到加密密文进行解密
  • 【拒绝算法PUA】LeetCode 2270. 分割数组的方案数
  • Dijkstra解决单源最短路径
  • 2.1 transformer模型原理及代码(python)
  • 深度学习常用操作笔记
  • 多重背包讲解
  • 使用TensorFlow时需掌握的Pandas核心知识点
  • JDK15开始偏向锁不再默认开启
  • Qt开发——问界M9空调
  • 强化学习的一些概念
  • 运维面试题(三)
  • Java虚拟机面试题:内存管理(中)
  • 【java】集合练习2
  • Chapter 4-11. Troubleshooting Congestion in Fibre Channel Fabrics
  • Nest系列:在 NestJS 中使用 Joi 进行环境变量验证与配置管理-03
  • Navicat如何查看密码
  • Chrome 浏览器的很多扩展不能用了
  • 数字签名与非对称加密的区别
  • LLM论文笔记 24: A Theory for Length Generalization in Learning to Reason
  • AJAX PHP:深入理解与实际应用
  • 首映丨纪录电影《滚烫年华》:献给所有奋斗者
  • 宇树科技王兴兴:第一桶金来自上海,欢迎上海的年轻人加入
  • 古埃及展进入百天倒计时,闭幕前168小时不闭馆
  • 中国证监会印发2025年度立法工作计划
  • 北外滩集团21.6亿元摘上海虹口地块,为《酱园弄》取景地
  • 前4个月我国货物贸易进出口同比增长2.4%,增速较一季度加快1.1个百分点