jetpack DataStore学习
2020-12-17 本文已影响0人
刘景昌
DataStore由来
Google 新增加了一个新 Jetpack 的成员 DataStore,主要用来替换 SharedPreferences, DataStore 应该是开发者期待已久的库,DataStore 是基于 Flow 实现的,一种新的数据存储方案,它提供了两种实现方式:
Proto DataStore:存储类的对象(typed objects ),通过 protocol buffers 将对象序列化存储在本地,protocol buffers 现在已经应用的非常广泛,无论是微信还是阿里等等大厂都在使用,我们在部分业务场景中也用到了 protocol buffers,会在后续的文章详细分析
Preferences DataStore:以键值对的形式存储在本地和 SharedPreferences 类似,但是 DataStore 是基于 Flow 实现的,不会阻塞主线程,并且保证类型安全
SharedPreference 所存在的问题
- 获取数据时,可能会导致主线程阻塞
- SharedPreference 不能保证类型安全
- SharedPreference 加载的数据会一直留在内存中,浪费内存
- apply() 方法虽然是异步的,可能会发生 ANR
- apply() 方法无法获取到操作成功或者失败的结果
DataStore优点
DataStore的出现就是为了解决SharedPreference 的缺点
他有以下有点
- DataStore 是基于 Flow 实现的,所以保证了在主线程的安全性
- 以事务方式处理更新数据,事务有四大特性(原子性、一致性、 隔离性、持久性)
- 没有 apply() 和 commit() 等等数据持久的方法
- 自动完成 SharedPreferences 迁移到 DataStore,保证数据一致性,不会造成数据损坏
- 可以监听到操作成功或者失败结果
DataStore需要使用的场景是和SharedPreference 一致的,适合存储简单、小型的数据,并且不支持局部更新。
如何在项目中使用
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha01"
实现工具类
class DataStoreUtil private constructor(){
lateinit var mDataStorePre : DataStore<Preferences>
fun init(context :Context) {
mDataStorePre = context.createDataStore("HintTest")
}
companion object {
val instance: DataStoreUtil by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { DataStoreUtil() }
}
}
/***
* 在DataStore读取信息
*/
suspend inline fun <reified T : Any> dataStoreSave(key: String,value: T) = when(T::class){
String::class -> DataStoreUtil.instance.mDataStorePre.edit { it[preferencesKey<T>(key)] = value }
Int::class -> DataStoreUtil.instance.mDataStorePre.edit { it[preferencesKey<T>(key)] = value }
Boolean::class -> DataStoreUtil.instance.mDataStorePre.edit { it[preferencesKey<T>(key)] = value }
else -> throw IllegalArgumentException("Type not supported: ${T::class.java}")
}
/***
* 在DataStore写入信息
*/
suspend inline fun <reified T : Any> dataStoreRead(key : String) = when(T::class){
String::class -> DataStoreUtil.instance.mDataStorePre.data.map { it[preferencesKey<T>(key)] ?: "" }.first() as T
Int::class -> DataStoreUtil.instance.mDataStorePre.data.map { it[preferencesKey<T>(key)] ?: 0 }.first() as T
Boolean::class -> DataStoreUtil.instance.mDataStorePre.data.map { it[preferencesKey<T>(key)] ?: false }.first() as T
else -> throw IllegalArgumentException("Type not supported: ${T::class.java}")
}
在外部使用方法
- 保存数据
lifecycleScope.launch {
dataStoreSave(KEY,value)
}
- 读取数据
lifecycleScope.launch {
Log.e("获取结果",dataStoreRead<String>(KEY))
}
```