DataStore 使用

DataStore 是Jetpack 组件之一,是Google 开发出来用以代替SharedPreferences 的。DataStore 是基于 Flow 实现的,一种新的数据存储方案,它提供了两种实现方式:

  • Proto DataStore:存储类的对象(typed objects ),通过 protocol buffers 将对象序列化存储在本地
  • Preferences DataStore:以键值对的形式存储在本地和 SharedPreferences 类似,但是 DataStore 是基于 Flow 实现的,不会阻塞主线程,并且保证类型安全

Preferences DataStore 相比于 SharedPreferences 优点

  • DataStore 是基于 Flow 实现的,所以保证了在主线程的安全性
  • 以事务方式处理更新数据,事务有四大特性(原子性、一致性、 隔离性、持久性)
  • 没有 apply() 和 commit() 等等数据持久的方法
  • 自动完成 SharedPreferences 迁移到 DataStore,保证数据一致性,不会造成数据损坏
  • 可以监听到操作成功或者失败结果

一. 使用

1. 依赖
implementation "androidx.datastore:datastore-preferences:1.0.0-beta01"
implementation "androidx.datastore:datastore:1.0.0-beta01"

// protobuf
 implementation "com.google.protobuf:protobuf-javalite:3.10.0"
2. 创建DataStore 对象
// 'settings' 是存储在本地的文件名
private val prefDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
3. 读和写

这里以String 类型为例,其余数据类型同理,
读数据

// 返回一个Flow
fun getString(key: String, dft: String = ""): Flow<String> {
        return prefDataStore.data.catch { e ->  // Flow 中发生异常可使用这种方式捕获,catch 块是可选的
            if (e is IOException) {
                e.printStackTrace()
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {
            it[stringPreferencesKey(key)] ?: dft       // stringPreferencesKey 生成一个读取string 类型的key
        }
}

写数据

suspend fun putString(key: String, value: String) {
        // edit 函数需要在挂起环境中执行
        prefDataStore.edit { pref -> pref[stringPreferencesKey(key)] = value }
}

上面的读和写都是在协程的环境中执行的,是非阻塞的,如果要使用阻塞的形式,可以通过 runBlocking方法,如:

fun getStringSync(key: String, dft: String = ""): String {
        var value = dft
        runBlocking {
            prefDataStore.data.first {
                value = it[stringPreferencesKey(key)] ?: dft
                true          // 这里返回true 表示取到Flow 中的第一个数据后停止收集Flow 中的数据
            }
        }
        return value
}

迁移SharedPreferences
迁移 SharedPreferences 到 DataStore 只需要 2 步

  • 在构建 DataStore 的时候,需要传入一个 SharedPreferencesMigration
dataStore = context.createDataStore(
    name = PREFERENCE_NAME,
    migrations = listOf(
        SharedPreferencesMigration(
            context,
            SharedPreferencesRepository.PREFERENCE_NAME    // 创建SharedPreferences 时的文件名
        )
    )
)
  • 当 DataStore 对象构建完了之后,需要执行一次读取或者写入操作,即可完成 SharedPreferences 迁移到 DataStore,当迁移成功之后,会自动删除 SharedPreferences 使用的文件

注意: 只从 SharedPreferences 迁移一次,因此一旦迁移成功之后,应该停止使用 SharedPreferences。

二. 对比

与MMKV 的对比


image.png

Google 提供的一个SharedPreferences 和DataStore 对比图


image.png

参考文档:
https://juejin.cn/post/6881442312560803853
https://juejin.cn/post/6888847647802097672
https://developer.android.com/topic/libraries/architecture/datastore#kotlin

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Jetpack 的 DataStore 是一种数据存储解决方案,可以像 SharedPreferences 一样存...
    TTTqiu阅读 1,754评论 1 2
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 126,116评论 2 7
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,113评论 0 4