環境
windows 10 AndroidStudio 3.0.1 protobuf-javalite 版本
初始配置
#####1. project.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// protobuf支援版本,AS3.0必須用0.8.2以上
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
複製程式碼
#####2. modle.gradel
apply plugin: 'com.google.protobuf'
android {
sourceSets {
main {
proto {
srcDir 'src/main/proto' //proto檔案所在路徑
include '**/*.proto'
}
java {
srcDir 'src/main/java'
}
}
}
}
protobuf {
protoc {
// You still need protoc like in the non-Android case
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
javalite {
// The codegen for lite comes as a separate artifact
artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
// In most cases you don't need the full Java output
// if you use the lite output.
remove java
}
task.plugins {
javalite { }
}
}
}
//將會在 "$projectDir/src/generated"這個目錄中自動生成對應的java檔案
generatedFilesBaseDir = "$projectDir/src/generated"
}
dependencies {
compile 'com.google.protobuf:protobuf-lite:3.0.0'
}
複製程式碼
#####3. AndroidStudio中安裝外掛:
#####4. 編寫.proto檔案 因為在gradle中設定了proto檔案的可編譯目錄,所以需要在這個目錄中編寫.proto檔案 (參考網上教程寫了proto檔案,但具體網址不記得了,不好意思,如果需要我會備註)
syntax = "proto3";
package tutorial;
option java_package = "com.je.pro.test";
option java_outer_classname = "ResponsePB";
message Tab {
int32 type = 1;
string f = 2;
}
message ItemData {
string sname = 1;
string packageid = 2;
repeated Tab tabs = 45;
}
message DataItem {
int32 datatype = 1;
ItemData itemdata = 2;
}
message Response {
repeated DataItem data = 1;
bool hasNextPage = 2;
string dirtag = 3;
}
複製程式碼
初次使用,proto的語法都是參考網上教程,若有失誤,謝謝指正。 寫完後,點選
即可自動生成java檔案。####生成目錄結構:
資料生成和解析
#####1. 資料生成 程式碼:
public byte[] testGetBytes(){
ResponsePB.Tab.Builder tabBuilder = ResponsePB.Tab.newBuilder().setF("sss").setType(2);
ResponsePB.ItemData.Builder itemData = ResponsePB.ItemData.newBuilder();
itemData.setPackageid("222222");
itemData.setSname("eiiii");
itemData.addTabs(tabBuilder);
ResponsePB.Response.Builder responseBuilder = ResponsePB.Response.newBuilder();
responseBuilder.setHasNextPage(true);
responseBuilder.setDirtag("soft");
ResponsePB.DataItem.Builder dataItem = ResponsePB.DataItem.newBuilder().setDatatype(1).setItemdata(itemData);
ResponsePB.Response response = responseBuilder.addData(dataItem).build();
System.out.println(response.toString());
byte[] out = response.toByteArray();
return out;
}
複製程式碼
列印出
data {
datatype: 1
itemdata {
packageid: "222222"
sname: "eiiii"
tabs {
f: "sss"
type: 2
}
}
}
dirtag: "soft"
has_next_page: true
複製程式碼
#####1. 解析 程式碼:
public void testDeBytes(){
byte[] out = testGetBytes();
try {
ResponsePB.Response test = ResponsePB.Response.parseFrom(out);
System.out.println(test.getData(0));
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
複製程式碼
列印出:
datatype: 1
itemdata {
packageid: "222222"
sname: "eiiii"
tabs {
f: "sss"
type: 2
}
}
複製程式碼
這樣簡單的應用就完成了。
專案中遇到問題與解決:
- 需要重利用資料:option allow_alias = true;
enum Test{
option allow_alias = true;
test_value=2;
duplicate_test_value=2;
}
複製程式碼
原本在enum中不能定義相同的值,但加入option allow_alias = true;
就可以了
- repeated變數使用 正確方式
ResponsePB.Tab.Builder tabBuilder = ResponsePB.Tab.newBuilder().setF("sss").setType(2);
ResponsePB.ItemData.Builder itemData = ResponsePB.ItemData.newBuilder();
itemData.addTabs(tabBuilder);
複製程式碼
錯誤方式
ResponsePB.Tab.Builder tabBuilder = ResponsePB.Tab.newBuilder().setF("sss").setType(2);
ResponsePB.ItemData.Builder itemData = ResponsePB.ItemData.newBuilder();
itemData.setTabs(0,tabBuilder);
複製程式碼
報異常:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.set(ArrayList.java:444)
at com.google.protobuf.ProtobufArrayList.set(ProtobufArrayList.java:96)
at com.je.pro.test.ResponsePB$ItemData.setTabs(ResponsePB.java:590)
at com.je.pro.test.ResponsePB$ItemData.access$1500(ResponsePB.java:429)
at com.je.pro.test.ResponsePB$ItemData$Builder.setTabs(ResponsePB.java:881)
at com.je.pro.ExampleUnitTest.testByte(ExampleUnitTest.java:91)
複製程式碼
這個異常可以參考ArrayList.set() 方法,不要懷疑,我真的直接set了 附上ArrayList add() set() 原始碼
/**
* Replaces the element at the specified position in this list with
* the specified element.
*
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
複製程式碼
參考網站
developers.google.com/protocol-bu… github.com/google/prot… github.com/protocolbuf…