当前位置:   article > 正文

Android中的DataStore-Proto_android datastore

android datastore

一、前言

Android中本地存储一些简单类型的数据时候通常使用SharePreferences,但是由于对异步操作支持不太好,所以在新的版本中提供了DataStore进行数据存储。DataStore有两个不同的实现,Datastore PreferencesProto Datastore。这两种实现有以下区别:

  • Preferences DataStore 使用键存储和访问数据。此实现不需要预定义的架构,也不确保类型安全。
  • Proto DataStore 将数据作为自定义数据类型的实例进行存储。此实现要求您使用协议缓冲区来定义架构,但可以确保类型安全。

为了能解决掉SharePreferences所存在的弊端,这里只对Proto Datastore的使用方式进行记录。

二、相关依赖

在实际使用中除了DataStore的依赖还需要添加一些其它的依赖。

  • Protocol的依赖,用于实现类型化安全

  • 协程coroutines的依赖,因为DataStore使用了Flow作为数据流处理

  • 由于DataStore需要在异步环境中使用,为了更好配合jetpack,需要添加一些ktx拓展库,如livedata-ktxviewmodel-ktxlifecycle-ktx

整体依赖配置如下:

plugins {
    ...
    id "com.google.protobuf" version "0.8.12"
}

dependencies {
    //android一些库的ktx拓展
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
    //协程
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1'
    
    implementation  "androidx.datastore:datastore-core:1.0.0"
    implementation "androidx.datastore:datastore:1.0.0"
    implementation  "com.google.protobuf:protobuf-javalite:3.14.0"
    ...
}

protobuf {
    protoc {
        if (osdetector.os == "osx") {
            artifact = 'com.google.protobuf:protoc:3.14.0:osx-x86_64'
        } else {
            artifact = 'com.google.protobuf:protoc:3.14.0'
        }
    }

    // Generates the java Protobuf-lite code for the Protobufs in this project. See
    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
    // for more information.
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option 'lite'
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

三、创建Proto文件

需要在../app/src/main/处创建一个proto文件夹,该位置是proto文件存储的默认位置,如果需要更改的话,可以参考Android上使用Protocol Buffer_Mr_Tony的专栏-CSDN博客进行修改。创建完该文件夹后,在proto文件夹创建拓展名为.proto的文件(或者.pb)。其代码例子如下:

test.proto

syntax = "proto3";

option java_package = "com.example.application";
option java_multiple_files = true;

message Settings {
  int32 example_counter = 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

编写完后,进行build重新编译程序。会在app/build/generated/source/proto下面生成由java_package指定的文件夹,如com/example/application,下面生成由message指定的名字的Settings.java文件(其它类型的文件和分类规则参考protocol buffer官方文档)。

四、DataStore使用代码编写

待重新build生成文件后开始编写相关的DataStore代码了。其主要分为解析器Serializer的创建、DataStore的创建、DataStore的读取、DataStore的修改。其编写方式主要参考官方文档。如下:

object SettingsSerializer : Serializer<Settings> {
  override val defaultValue: Settings = Settings.getDefaultInstance()

  override suspend fun readFrom(input: InputStream): Settings {
    try {
      return Settings.parseFrom(input)
    } catch (exception: InvalidProtocolBufferException) {
      throw CorruptionException("Cannot read proto.", exception)
    }
  }

  override suspend fun writeTo(
    t: Settings,
    output: OutputStream) = t.writeTo(output)
}

val Context.settingsDataStore: DataStore<Settings> by dataStore(
  fileName = "settings.proto",
  serializer = SettingsSerializer
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

读取方式如下:

val exampleCounterFlow: Flow<Int> = context.settingsDataStore.data
  .map { settings ->
    // The exampleCounter property is generated from the proto schema.
    settings.exampleCounter
  }
  • 1
  • 2
  • 3
  • 4
  • 5

更新方式如下:

suspend fun incrementCounter() {
  context.settingsDataStore.updateData { currentSettings ->
    currentSettings.toBuilder()
      .setExampleCounter(currentSettings.exampleCounter + 1)
      .build()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

由于DataStore需要在异步环境中使用,所以尽量不要阻塞主线程,其具体使用方式如下,例如在Activity中使用

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleScope.launch(context = Dispatchers.IO){
            settingsDataStore.data.first()//读取方式
            incrementCounter()//写入方式
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

五、注意事项

使用过程中对Protocol的注意事项参考以下帖子:

Android上使用Protocol Buffer_Mr_Tony的专栏-CSDN博客

六、参考链接

  1. Android平台对DataStore的介绍

  2. Android Jetpack Proto DataStore

  3. Kotlin协程(一)_Mr_Tony的专栏-CSDN博客

  4. Language Guide (proto3)  |  Protocol Buffers  |  Google Developers

  5. 请不要滥用SharedPreference

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/419505
推荐阅读
相关标签
  

闽ICP备14008679号