添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
首发于 Jetpacker
DataStore(三)Proto DataStore

DataStore(三)Proto DataStore

DataStore不仅可以替代SharedPreferences,储存键值对,避免ANR问题,它还能够储存使用Protocol Buffers序列化过后的对象。

Protocol Buffers是Google提供的一种结构化数据储存格式。在DataStore中使用该格式对对象进行序列化和保存。

下面,我们一起来看看如何在DataStore中使用它。

1.第一步,需要在build.gradle文件中添加插件。

plugins {
    id "com.google.protobuf" version "0.8.12"//使用proto需要的插件
android {
protobuf { //使用proto需要的插件
    protoc {
        artifact = "com.google.protobuf:protoc:3.10.0"
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option 'lite'
dependencies {
    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha08"
    implementation "androidx.datastore:datastore:1.0.0-alpha08"
    implementation "com.google.protobuf:protobuf-javalite:3.10.0" //使用proto需要的插件
}

2.在 src/main/proto 目录下定义好.proto文件,通过Android Studio的Build功能,对整个项目进行编译,即可自动为你生成相关的代码。

假设我们定义了一个名为user_prefs.proto的文件。

syntax = "proto3";
option java_package = "com.michael.datastore";
option java_multiple_files = true;
message UserPreferences {
  string name = 1;
  int32 age = 2;
  bool sex = 3;
}

注意,字段中的1,2,3并不是字段的值,而是编号。关于Protocol Buffers的相关内容,大家可以自行搜索学习。不是本文所讨论的重点。

在编译完成后,可以看到Android Studio为我们生成的代码。

3.接下来,我们需要手动写一个Serializer类,用于序列化刚才Android Studio为我们生成的类文件UserPreferences。

object UserPreferencesSerializer : Serializer<UserPreferences> {
    override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance()
    override suspend fun readFrom(input: InputStream): UserPreferences {
        try {
            return UserPreferences.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            throw CorruptionException("Cannot read proto.", exception)
    override suspend fun writeTo(t: UserPreferences, output: OutputStream) = t.writeTo(output)
}

4.这些准备工作都做完以后,接下来就是DataStore的创建。依然,是通过属性委托进行创建。其中需要将我们刚才所写的Serializer类以参数的形式传入。

const val DATA_STORE_FILE_NAME = "user_prefs.pb"
//通过属性委托的方式创建
val Context.userProtoDataStore: DataStore<UserPreferences> by dataStore(
    fileName = DATA_STORE_FILE_NAME,
    serializer = UserPreferencesSerializer
object ProtoDataStore {
    private const val TAG: String = "ProtoDataStore"
    suspend fun read(context: Context) :Flow<UserPreferences>{
        return context.userProtoDataStore.data
            .catch { exception ->
                if (exception is IOException) {
                    Log.e(TAG, "Error reading sort order preferences.", exception)
                    emit(UserPreferences.getDefaultInstance())
                } else {
                    throw exception
    suspend fun write(context: Context, name: String, age: Int, sex: Boolean) {
        context.userProtoDataStore.updateData { currentPreferences ->
            currentPreferences.toBuilder().setName(name).setAge(age).setSex(sex).build()
}

5.读取和写入Proto DataStore

findViewById<Button>(R.id.btnPutProto).setOnClickListener {
            GlobalScope.launch {
                ProtoDataStore.write(applicationContext, "michael", 33, true)
                Log.e(">>>>>>>>>>>>", "写入数据")
findViewById<Button>(R.id.btnGetProto).setOnClickListener {
    GlobalScope.launch {
        Log.e(">>>>>>>>>>>>", "读取数据")
        try {
            val userPreferencesFlow: Flow<UserPreferences> =
                ProtoDataStore.read(applicationContext)
            userPreferencesFlow.collect { preferences ->
                Log.e(">>>>>>>>>>", "name:" + preferences.name)
                Log.e(">>>>>>>>>>", "age" + preferences.age)
                Log.e(">>>>>>>>>>", "sex" + preferences.sex)