当前位置:   article > 正文

Android DataStore_android datastore proto 设置默认值

android datastore proto 设置默认值

github blog
qq: 2383518170
wx: lzyprime

λ:

经过几番修改。对DataStore的封装方式初步定下,虽然还是不满意,但已经是目前能想到的最好的方式。等有了新想法再改。

目前:

// key
val UserId = stringPreferencesKey("user_id")

// use:
val userId = DS[UserId] // 取值
DS[UserId] = "new user id" // 设值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
// or delegate read and write:
var userId by UserId(defaultValue = "") // 需要设置属性为空时的默认值。userId: String
repo.login(userId)
userId = "new user id"
  • 1
  • 2
  • 3
  • 4
// or readOnly
val userId by UserId // 只读. userId: String?
if(!userId.isNullOrEmpty()) repo.login(userId)
  • 1
  • 2
  • 3

DS:

// DS:
@JvmInline
value class DSManager(private val dataStore: DataStore<Preferences>) : DataStore<Preferences> {
   
    ...
}

val DS: DSManager by lazy {
   ...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

提供了两套获取方式。一种是像map一样的访问风格。一种是靠属性委托的方式。运算符重载属性委托内联类(用于收缩函数范围)

记录一下是如何一步步混沌邪恶的。

DataStore API

DataStore 文档

当前DataStore 1.0.0,目的是替代之前的SharedPreference, 解决它的诸多问题。除了Preference简单的key-value形式,还有protobuf版本。但是感觉鸡肋,小数据key-value就够了,大数据建议Room处理数据库。所以介于中间的部分,或者真的需要类型化的,真的有吗?

DataStoreFlow的方式提供数据,所以跑在协程里,可以不阻塞UI。

interface

DataStore的接口非常简单,一个data, 一个fun updateData:

// T = Preferences
public interface DataStore<T> {
   
    public val data: Flow<T>
    public suspend fun updateData(transform: suspend (t: T) -> T): T
}

public suspend fun DataStore<Preferences>.edit(transform: suspend (MutablePreferences) -> Unit): Preferences {
   
    return this.updateData {
    it.toMutablePreferences().apply {
    transform(this) } }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

data: Flow<Preferences>Preferences可以看作是个Map<Preferences.Key<*>, Any>

同时为了数据修改方便,提供了个edit的拓展函数,调用的就是updateData函数。

获取实例

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "datastore_name")
  • 1

preferencesDataStore 只为Context下的属性提供只读的委托:ReadOnlyProperty<Context, DataStore<Preferences>>

所以前边非要定成Context的拓展属性,属性名不一定非是这个, val Context.DS by ... 也可以。

搞清楚kotlin的属性委托拓展属性,就懂了这行代码。

preferencesDataStore相当于创建了个fileDir/<datastore_name>.preferences_pb的文件, 存数据。

Preferences.Key

public abstract class Preferences internal constructor() {
   
    public class Key<T> internal constructor(public val name: String){
    ... }
}

//create: 
val USER_ID = stringPreferencesKey("user_id")
val Guide = booleanPreferencesKey("guide")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

都被加了internal限制,所以在外边调不了构造。然后通过stringPreferencesKey(name: String)等一系列函数,创建特定类型的Key, 好处是限定了类型的范围,不会创出不支持类型的Key, 比如Key<UserInfo>Key<List<*>>

同时通过Preferences.Key<T>保证类型安全,明确存的是T类型数据。而SharedPreference, 可以冲掉之前的值类型:

SharedPreference.edit{
   
    it["userId"] = 1 
    it["userId"] = "new user id"
}
  • 1
  • 2
  • 3
  • 4
  • 5

使用:

// 取值 -------------
val userIdFlow: Flow<String> = context.dataStore.data.map {
    preferences -><
  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/752800
推荐阅读
相关标签
  

闽ICP备14008679号