赞
踩
在Android中本地存储一些简单类型的数据时候通常使用SharePreferences
,但是由于对异步操作支持不太好,所以在新的版本中提供了DataStore
进行数据存储。DataStore
有两个不同的实现,Datastore Preferences
和Proto Datastore
。这两种实现有以下区别:
为了能解决掉SharePreferences
所存在的弊端,这里只对Proto Datastore
的使用方式进行记录。
在实际使用中除了DataStore
的依赖还需要添加一些其它的依赖。
Protocol
的依赖,用于实现类型化安全
协程coroutines
的依赖,因为DataStore
使用了Flow
作为数据流处理
由于DataStore
需要在异步环境中使用,为了更好配合jetpack,需要添加一些ktx拓展库,如livedata-ktx
、viewmodel-ktx
、lifecycle-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' } } } } }
需要在../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;
}
protocol buffer
的语法规则参考Language Guide (proto3) | Protocol Buffers | Google Developers。编写完后,进行build重新编译程序。会在app/build/generated/source/proto
下面生成由java_package
指定的文件夹,如com/example/application
,下面生成由message
指定的名字的Settings.java
文件(其它类型的文件和分类规则参考protocol buffer
官方文档)。
待重新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 )
读取方式如下:
val exampleCounterFlow: Flow<Int> = context.settingsDataStore.data
.map { settings ->
// The exampleCounter property is generated from the proto schema.
settings.exampleCounter
}
更新方式如下:
suspend fun incrementCounter() {
context.settingsDataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setExampleCounter(currentSettings.exampleCounter + 1)
.build()
}
}
由于DataStore
需要在异步环境中使用,所以尽量不要阻塞主线程,其具体使用方式如下,例如在Activity中使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch(context = Dispatchers.IO){
settingsDataStore.data.first()//读取方式
incrementCounter()//写入方式
}
}
使用过程中对Protocol
的注意事项参考以下帖子:
Android上使用Protocol Buffer_Mr_Tony的专栏-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。