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 by preferencesDataStore(name = "settings")
3. 读和写

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

// 返回一个Flow
fun getString(key: String, dft: String = ""): Flow {
        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

你可能感兴趣的:(DataStore 使用)