Jetpack的DataStore存储超级详细教程——Proto DataStore
前言
Proto DataStore使用方法相对Preferences DataStore较为复杂,导入插件和依赖,编写proto文件,编译项目,才可以使用
环境(仅供参考):Android Studio4.1 + kotlin1.3.21 + androidx + 协程
使用步骤
导入插件和依赖,配置proto(主项目build上添加)
1、导入plugins 插件
plugins {
id "com.google.protobuf" version "0.8.12" // 第一步
}
2、导入依赖包
// 在调用api的时候,使用了
api "androidx.datastore:datastore-preferences:1.0.0-alpha06"
// proto主要使用
api "androidx.datastore:datastore-core:1.0.0-alpha06"
api "com.google.protobuf:protobuf-javalite:3.10.0"
3、配置 protoc 命令(最外层写入)
/**
* 注意配置 protoc 命令,分为不同的版本,版本不同配置的方式不同,
* 网上大部分都是 3.0.x ~ 3.7.x 的配置方式,关于这种配置方法,可以查看 [protobuf-gradle-plugin](https://github.com/google/protobuf-gradle-plugin) 文档,
* 这里不在演示了,也不建议使用
* 在此项目中使用的是 3.8 以后 的配置的配置,
*/
protobuf {
// 设置 protoc 的版本
protoc {
// //从仓库下载 protoc 这里的版本号需要与依赖 com.google.protobuf:protobuf-javalite:xxx 版本相同
artifact = 'com.google.protobuf:protoc:3.10.0'
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
}
}
}
}
// 默认生成目录 $buildDir/generated/source/proto 通过 generatedFilesBaseDir 改变生成位置
generatedFilesBaseDir = "$projectDir/src/main"
}
4、设置 proto 文件位置
android {
sourceSets {
main {
proto {
// proto 文件默认路径是 src/main/proto
// 可以通过 srcDir 修改 proto 文件的位置
srcDir 'src/main/proto'
}
}
}
}
编译一下项目
完整代码如下
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id "com.google.protobuf" version "0.8.12" // 第一步
}
androidExtensions { // 需要kotlin-android-extensions支持
experimental = true
}
android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.datastoredemo"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
// 设置 proto 文件位置
sourceSets {
main {
proto {
// proto 文件默认路径是 src/main/proto
// 可以通过 srcDir 修改 proto 文件的位置
srcDir 'src/main/proto'
}
}
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// Typed DataStore (Typed API surface, such as Proto)
// Preferences DataStore (SharedPreferences like APIs)
api "androidx.datastore:datastore-preferences:1.0.0-alpha06"
// Typed DataStore (Typed API surface, such as Proto)
api "androidx.datastore:datastore-core:1.0.0-alpha06"
implementation "com.google.protobuf:protobuf-javalite:3.10.0"
// mmkv存储
implementation 'com.tencent:mmkv-static:1.2.7'
}
/**
* 注意配置 protoc 命令,分为不同的版本,版本不同配置的方式不同,
* 网上大部分都是 3.0.x ~ 3.7.x 的配置方式,关于这种配置方法,可以查看 [protobuf-gradle-plugin](https://github.com/google/protobuf-gradle-plugin) 文档,
* 这里不在演示了,也不建议使用
* 在此项目中使用的是 3.8 以后 的配置的配置,
*/
protobuf {
// 设置 protoc 的版本
protoc {
// //从仓库下载 protoc 这里的版本号需要与依赖 com.google.protobuf:protobuf-javalite:xxx 版本相同
artifact = 'com.google.protobuf:protoc:3.10.0'
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
}
}
}
}
// 默认生成目录 $buildDir/generated/source/proto 通过 generatedFilesBaseDir 改变生成位置
generatedFilesBaseDir = "$projectDir/src/main"
}
编写proto文件以及编译
1、在app/src/main目录下新建一个文件proto
2、在文件夹proto下新建一个.proto类型的文件(如UserPrefs.proto)
3、编写proto文件及其字段
// 固定的,有proto2,但是proto3更好
syntax="proto3";
// 格式:包名 + . + 文件名
option java_package = "com.example.datastoredemo.protobuf";
// 格式:字段类型 + 字段名称 + 字段编号 = 编号(唯一)
message UserPreferences {
string query = 1; // String类型
int32 page_number = 2; // int类型 sint32
int64 result_per_page = 3;// long类型 sint64
bool age = 4;// boolean类型
double student_name = 5;// double类型
float student_fs = 6;// float类型
bytes student_fs_dd = 7;// bytes类型
}
完整结构如下
4、编译:需要的字段添加好了后,ReBuild Project一下,可以看到自动生成的文件,如下:
具体使用
1、定义一个实现 Serializer 的类
import androidx.datastore.core.Serializer
import com.example.datastoredemo.protobuf.UserPrefs
import java.io.InputStream
import java.io.OutputStream
/**
* 作者: CQ
* 日期: 2021-03-31
* 说明: 序列化
*/
object UserPreferencesSerializer: Serializer<UserPrefs.UserPreferences> {
override val defaultValue: UserPrefs.UserPreferences
get() = UserPrefs.UserPreferences.getDefaultInstance()
override fun readFrom(input: InputStream): UserPrefs.UserPreferences {
return UserPrefs.UserPreferences.parseFrom(input)
}
override fun writeTo(t: UserPrefs.UserPreferences, output: OutputStream) {
t.writeTo(output)
}
}
2、在需要使用的地方创建DataStore实例
private val dataStore: DataStore<UserPrefs.UserPreferences> =
this.createDataStore(fileName = "UserPrefs.pb", serializer = UserPreferencesSerializer)
3、写入
GlobalScope.launch { // 配合协程使用
dataStore.updateData {
// build模式调用
it.toBuilder().setResultPerPage(50).setPageNumber(20).build()
it.toBuilder().setAge(true).build()
}
}
4、读取
GlobalScope.launch {
dataStore.data.map {
it
}.collect { //flow 调用collect 开始消费数据
Log.e("TAG", "onCreate1: ${it}") //打印出所有数据
}
}
打印结果
com.example.datastoredemo.protobuf.UserPrefs$UserPreferences@737f98cf
age: true
page_number: 2
result_per_page: 50
操作大致如此。
喜欢的靓仔可以收藏关注喔
如有错误,还请指出,🈶🈚王者?