簡介
Google Protocol Buffers 簡稱 Protobuf,類似 json 或 XML军掂,是一種序列化結(jié)構(gòu)數(shù)據(jù)的機(jī)制,但是比它們更小昨悼、更快蝗锥、更簡單。同時支持多語言率触,跨平臺终议。
目前主要有兩個大版本:proto2 和 proto3。
其中 proto2 支持 Java葱蝗、Python穴张、 Objective-C、和 C++
两曼。
proto3 增加了對Go皂甘、JavaNano、Ruby悼凑、和 C#
的支持偿枕。
proto例子
syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
option java_package = "com.katyusha.aron.demo";
option java_outer_classname = "AddressBookProtos";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
Protobuf使用.proto
文件來定義數(shù)據(jù)格式,并同時提供編譯器將這些文件編譯為各種語言的源碼户辫。
message 格式非常簡單渐夸。每種類型的 message 包含一個或者多個唯一編碼字段,每個字段由名稱和值類型組成渔欢,值類型可以是數(shù)字(整形或者浮點型)墓塌、布爾值、字符串、原始字節(jié)桃纯,甚至是其他的 message(如上例所示)酷誓。Protobuf 允許 message 中包含 message,以達(dá)到分層嵌套态坦。
值得注意的一點是盐数,每個屬性都有唯一的一個tag
,上面的0,1,2...
等伞梯,這些tag
非常重要玫氢,是 Prodobuf 編碼時使用的對每個屬性的唯一標(biāo)識符————Prodobuf 并不使用屬性名(name,id,email...
)來編碼。因而谜诫,在定義過一個 message 之后漾峡,原則上都不應(yīng)該再修改每個屬性的tag
,因為一旦修改喻旷,可能就會出現(xiàn)新老數(shù)據(jù)版本解析出錯的問題生逸。
關(guān)鍵字
- syntax:聲明版本。例如上面
syntax="proto3"
且预,如果沒有聲明槽袄,則默認(rèn)是proto2
。 - package:聲明包名.
- import:導(dǎo)入包锋谐。類似于java遍尺,例如上面導(dǎo)入了
timestamp.proto
包。 - java_package:指定生成的類應(yīng)該放在什么Java包名下涮拗。如果你沒有顯式地指定這個值乾戏,則它簡單地匹配由package 聲明給出的Java包名,但這些名字通常都不是合適的Java包名 (由于它們通常不以一個域名打頭)三热。
- java_outer_classname:定義應(yīng)該包含這個文件中所有類的類名鼓择。如果你沒有顯式地給定java_outer_classname ,則將通過把文件名轉(zhuǎn)換為首字母大寫來生成就漾。例如上面例子編譯生成的文件名和類名是
AddressBookProtos
惯退。 - message:類似于java中的class關(guān)鍵字。
- repeated:用于修飾屬性从藤,表示對應(yīng)的屬性是個
array
。
更多的關(guān)鍵字可以參考官方文檔锁蠕,這里不做介紹夷野。
在Android中的使用
先來看一下是proto在安卓使用中的流程:
- 首先創(chuàng)建proto文件,該文件定義了你要使用的數(shù)據(jù)的數(shù)據(jù)格式荣倾。
- 通過proto文件悯搔,編譯生成proto java class,生成的類中包含你需要的getter/setter舌仍,這個java class就類似于我們平常所用的java bean妒貌,但其還包含很多很多的別的功能函數(shù)通危。在android中, 我們可以通過集成Gradle Plugin for Protobuf來編譯proto文件灌曙。
Android Studio 配置
- 在項目根的gradle文件中添加如下內(nèi)容:
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
}
}
- 在app module下的gradle文件中:
1 , 在apply plugin: 'com.android.application'
后添加apply plugin: 'com.google.protobuf'
2, 添加protobuf塊(與android同級):
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.5.1' // 也可以配置本地編譯器路徑
}
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.builtins {
java {}// 生產(chǎn)java源碼
}
}
}
}
3, 指定.proto文件的路徑:
sourceSets {
main {
java {
srcDir 'src/main/java'
}
proto {
srcDir 'src/main/proto' //指定.proto文件路徑
}
}
}
4 , 添加依賴:
api 'com.google.protobuf:protobuf-java:3.5.1'
api 'com.google.protobuf:protoc:3.5.1'
到這菊碟,android gradle環(huán)境就配置好了。此時可以編譯你的項目在刺,會生成proto java class逆害。這個類就是我們app后面要使用的。
- 代碼示例
定義proto文件:
syntax = "proto3";
package tutorial;
message Person {
string name = 1;
int32 id = 2;
string email = 3;
string phone = 4;
}
通過網(wǎng)絡(luò)獲取數(shù)據(jù)流蚣驼,然后解析成proto文件定義的格式:
Request request = new Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
Response response = call.execute();
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
return Person.parseFrom(responseBody.byteStream());
}
}
有了Person實體類魄幕,就可以在界面進(jìn)行顯示了:
textView.setText(person.toString());