文章目录
0. 一句话描述protobuf
protobuf是Google推出的类似json和xml一样的通信数据协议。
1. 为什么使用protobuf
1.1 轻松的定义和多语言生成
定义register.proto文件
syntax = "proto3";
package com.privi.protocol;
option java_outer_classname = "RegisterProtoCreator";
message RegisterProto {
string name = 1;
int32 age = 2;
}
使用插件即可生成多语言的类,供多语言使用。
1.2 高效
相对json,protobuf的时间和空间效率都很高,尤其适用于高频率大数据量的传输和解析。
2. Android studio使用protobuf基础篇
2.1 修改项目根build.gradle
buildscript {
//省略repostories
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
///**修改**:添加对protobuf插件的依赖
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
}
}
2.2 修改项目内build.gradle
apply plugin: 'com.android.library'
apply plugin: 'com.google.protobuf'
android {
//省略defaultConfig和buildTypes
///**修改1**:增加proto文件目录配置
sourceSets {
main {
// 定义proto文件目录
proto {
srcDir 'src/main/proto'
}
}
}
}
///**修改2**:增加protobuf插件编译配置
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
javalite {
artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
}
}
generateProtoTasks {
all().each { task ->
task.plugins {
javalite {}
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
///修改3:增加protobuf-lite包依赖
api 'com.google.protobuf:protobuf-lite:3.0.0'
}
2.3 定义proto文件
在src/main/proto目录下定义Register.proto
2.4 编译并查看类文件
使用gradle的单模块编译命令:gradlew :模块名:编译类型
terminal中执行 gradlew :protocol:assembleDebug
或者clean Project也可以。
在目录:\protocol\build\generated\source\proto\debug\javalite\com\privi\protocol\RegisterProtoCreator.java
即可以看拿到生成的类文件如下图:
3. 遇到的坑
3.1 问题1
编译报错:Configuration with name ‘debugAndroidTestCompile’ not found.
原因:根build.gradle下的protobuf 插件版本不是最新版本
解决方案:修改依赖为最新的protobuf 插件
参考:https://stackoverflow.com/questions/49772940/google-cloud-speech-api-protobuf-is-causing-debugandroidtestcompile-not-found
3.2 问题2
编译报错:Android - API ‘variant.getJavaCompiler()’ is obsolete and has been replaced with 'variant.getJavaCom
原因:gradle版本太新了,比如 3.3.0以上,protobuf 插件暂不支持该版本
解决方案:降低gradle 版本,比如降到gradle 3.2.1
3.3 问题3
编译报错:ResGetMapList.proto:11:5: “com.ainirobot.navigationservice.protocol.request.Params” seems to be defined in “ReqPackLog.proto”, which is not imported by “ResGetMapList.proto”. To use it here, please add the necessary import.
原因:在不同的proto文件中,定义同名的message会出错
解决方案:如果message内容相同,则单独定义proto文件,复用,如果message内容不同,则修改名字
3.4 问题4
编译报错:Error: Program type already present: com.google.protobuf.AbstractMessageLite
B
u
i
l
d
e
r
Builder
BuilderLimitedInputStream
原因:混用了protobuf-lite和protobuf-java,这两个属于protobuf的不同版本包,不能混用
解决方案:保证只用一种protobuf包
3.5 问题5
编译报错:找不到com.google.protobuf.MessageLiteOrBuilder的类文件
原因:protocol module使用了implementation依赖protobuf-lite包,app项目依赖protocol module的时候,就无法同时依赖protobuf-lite。
解决方案:用api替代依赖选项implementation