前言
- 習(xí)慣用
Json声功、XML
數(shù)據(jù)存儲(chǔ)格式的你們全度,相信大多都沒(méi)聽(tīng)過(guò)Protocol Buffer
-
Protocol Buffer
其實(shí) 是Google
出品的一種輕量 & 高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,性能比Json、XML
真的強(qiáng)域醇!太!多!
由于
Protocol Buffer
已經(jīng)具備足夠的吸引力
- 今天青伤,我將詳細(xì)介紹
Protocol Buffer
在Android
平臺(tái) 的具體使用
Carson帶你學(xué)序列化Protocol Buffer系列文章
快來(lái)看看Google出品的Protocol Buffer,別只會(huì)用Json和XML了
Carson帶你學(xué)序列化:手把手教你如何安裝Protocol Buffer
Carson帶你學(xué)序列化:全面詳解ProtocolBuffer語(yǔ)法
Carson帶你學(xué)序列化:Google出品的序列化神器Protocol Buffer使用指南
Carson帶你學(xué)序列化:Protocol Buffer序列化原理大揭秘-為什么性能這么好殴瘦?
Carson帶你學(xué)序列化:深入源碼分析Protocol Buffer
Carson帶你學(xué)序列化:深入分析JSON多種解析方式(Gson狠角、AS自帶org.json、Jackson)
Carson帶你學(xué)序列化:深入分析XML多種解析方式(DOM蚪腋、SAX丰歌、PULL)
目錄
1. 定義
一種 結(jié)構(gòu)化數(shù)據(jù) 的數(shù)據(jù)存儲(chǔ)格式(類似于 XML、Json
)
Protocol Buffer
目前有兩個(gè)版本:proto2
和proto3
- 因?yàn)?code>proto3 還是beta 版屉凯,所以本次講解是
proto2
2. 作用
通過(guò)將 結(jié)構(gòu)化的數(shù)據(jù) 進(jìn)行 串行化(序列化)立帖,從而實(shí)現(xiàn) 數(shù)據(jù)存儲(chǔ) / RPC 數(shù)據(jù)交換的功能
- 序列化: 將 數(shù)據(jù)結(jié)構(gòu)或?qū)ο?轉(zhuǎn)換成 二進(jìn)制串 的過(guò)程
- 反序列化:將在序列化過(guò)程中所生成的二進(jìn)制串 轉(zhuǎn)換成 數(shù)據(jù)結(jié)構(gòu)或者對(duì)象 的過(guò)程
3. 特點(diǎn)
- 對(duì)比于 常見(jiàn)的
XML、Json
數(shù)據(jù)存儲(chǔ)格式悠砚,Protocol Buffer
有如下特點(diǎn):
4. 應(yīng)用場(chǎng)景
傳輸數(shù)據(jù)量大 & 網(wǎng)絡(luò)環(huán)境不穩(wěn)定 的數(shù)據(jù)存儲(chǔ)晓勇、RPC 數(shù)據(jù)交換 的需求場(chǎng)景
如 即時(shí)IM (QQ、微信)的需求場(chǎng)景
總結(jié)
在 傳輸數(shù)據(jù)量較大的需求場(chǎng)景下灌旧,Protocol Buffer
比XML绑咱、Json
更小、更快枢泰、使用 & 維護(hù)更簡(jiǎn)單描融!
5. 使用流程
- 使用
Protocol Buffer
的流程如下:
- 今天主要講解
Protocol Buffer
在Android
平臺(tái) 的具體使用
6. 應(yīng)用實(shí)例(Android平臺(tái))
- 具體步驟如下:
步驟1:將生成的 代碼文件 放入到項(xiàng)目中
- 對(duì)于
Android(Java)平臺(tái)
,即將編譯.proto
文件生成的Java
包文件 整個(gè)復(fù)制到Android
項(xiàng)目中 - 放置路徑:
app/src/main/java的
文件夾里
步驟2:在 Gradle
添加 Protocol Buffer
版本依賴
compile 'com.google.protobuf:protobuf-java:2.6.1'
// 注:protobuf-java的版本 一定要和 安裝protocobuffer的版本 一致
步驟3:具體在Android項(xiàng)目中使用
3.1 消息對(duì)象類介紹
通過(guò).proto文件
轉(zhuǎn)換的 Java
源代碼 = Protocol Buffer
類 + 消息對(duì)象類(含Builder
內(nèi)部類)
消息對(duì)象類 是
Protocol Buffer
類的內(nèi)部類
由于最常用的都是 消息對(duì)象類 和其內(nèi)部類Builder
類 的方法&成員變量衡蚂,所以此處主要講解這兩者窿克。
3.1.1 消息對(duì)象類(Message
類)
- 消息對(duì)象類 類通過(guò) 二進(jìn)制數(shù)組 寫 和 讀 消息類型
- 使用方法包括:
<-- 方式1:直接序列化和反序列化 消息 -->
protocolBuffer.toByteArray();
// 序列化消息 并 返回一個(gè)包含它的原始字節(jié)的字節(jié)數(shù)組
protocolBuffer.parseFrom(byte[] data)毛甲;
// 從一個(gè)字節(jié)數(shù)組 反序列化(解析) 消息
<-- 方式2:通過(guò)輸入/ 輸出流(如網(wǎng)絡(luò)輸出流) 序列化和反序列化消息 -->
protocolBuffer.writeTo(OutputStream output)年叮;
output.toByteArray();
// 將消息寫入 輸出流 ,然后再 序列化消息
protocolBuffer.parseFrom(InputStream input)丽啡;
// 從一個(gè) 輸入流 讀取并 反序列化(解析)消息
// 只含包含字段的getters方法
// required string name = 1;
public boolean hasName();// 如果字段被設(shè)置谋右,則返回true
public java.lang.String getName();
// required int32 id = 2;
public boolean hasId();
public int getId();
// optional string email = 3;
public boolean hasEmail();
public String getEmail();
// repeated .tutorial.Person.PhoneNumber phone = 4;
// 重復(fù)(repeated)字段有一些額外方法
public List<PhoneNumber> getPhoneList();
public int getPhoneCount();
// 列表大小的速記
// 作用:通過(guò)索引獲取和設(shè)置列表的特定元素的getters和setters
常用的如上,更多請(qǐng)看官方文檔
3.1.2 Builder
類
作用:創(chuàng)建 消息構(gòu)造器 & 設(shè)置/ 獲取消息對(duì)象的字段值 & 創(chuàng)建 消息類 實(shí)例
屬于 消息對(duì)象類 的內(nèi)部類
a. 創(chuàng)建 消息構(gòu)造器
Demo.Person.Builder person = Person.newBuilder();
b. 設(shè)置/ 獲取 消息對(duì)象的字段值 具體方法如下:
// 標(biāo)準(zhǔn)的JavaBeans風(fēng)格:含getters和setters
// required string name = 1;
public boolean hasName();// 如果字段被設(shè)置补箍,則返回true
public java.lang.String getName();
public Builder setName(String value);
public Builder clearName(); // 將字段設(shè)置回它的空狀態(tài)
// required int32 id = 2;
public boolean hasId();
public int getId();
public Builder setId(int value);
public Builder clearId();
// optional string email = 3;
public boolean hasEmail();
public String getEmail();
public Builder setEmail(String value);
public Builder clearEmail();
// repeated .tutorial.Person.PhoneNumber phone = 4;
// 重復(fù)(repeated)字段有一些額外方法
public List<PhoneNumber> getPhoneList();
public int getPhoneCount();
// 列表大小的速記
// 作用:通過(guò)索引獲取和設(shè)置列表的特定元素的getters和setters
public PhoneNumber getPhone(int index);
public Builder setPhone(int index, PhoneNumber value);
public Builder addPhone(PhoneNumber value);
// 將新元素添加到列表的末尾
public Builder addAllPhone(Iterable<PhoneNumber> value);
// 將一個(gè)裝滿元素的整個(gè)容器添加到列表中
public Builder clearPhone();
public Builder isInitialized()
// 檢查所有 required 字段 是否都已經(jīng)被設(shè)置
public Builder toString() :
// 返回一個(gè)人類可讀的消息表示(用于調(diào)試)
public Builder mergeFrom(Message other)
// 將 其他內(nèi)容 合并到這個(gè)消息中改执,覆寫單數(shù)的字段,附接重復(fù)的坑雅。
public Builder clear()
// 清空所有的元素為空狀態(tài)辈挂。
3.2 具體使用
使用步驟如下:
步驟1:通過(guò) 消息類的內(nèi)部類Builder
類 構(gòu)造 消息構(gòu)造器
步驟2:通過(guò) 消息構(gòu)造器 設(shè)置 消息字段的值
步驟3:通過(guò) 消息構(gòu)造器 創(chuàng)建 消息類 對(duì)象
步驟4:序列化 / 反序列化 消息具體使用如下:(注釋非常清晰)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 步驟1:通過(guò) 消息類的內(nèi)部類Builder類 構(gòu)造 消息類的消息構(gòu)造器
Demo.Person.Builder personBuilder = Demo.Person.newBuilder();
// 步驟2:設(shè)置你想要設(shè)置的字段為你選擇的值
personBuilder.setName("Carson");// 在定義.proto文件時(shí),該字段的字段修飾符是required,所以必須賦值
personBuilder.setId(123);// 在定義.proto文件時(shí),該字段的字段修飾符是required,所以必須賦值
personBuilder.setEmail("carson.ho@foxmail.com"); // 在定義.proto文件時(shí),該字段的字段修飾符是optional,所以可賦值 / 不賦值(不賦值時(shí)將使用默認(rèn)值)
Demo.Person.PhoneNumber.Builder phoneNumber = Demo.Person.PhoneNumber.newBuilder();
phoneNumber.setType( Demo.Person.PhoneType.HOME);// 直接采用枚舉類型里的值進(jìn)行賦值
phoneNumber.setNumber("0157-23443276");
// PhoneNumber消息是嵌套在Person消息里,可以理解為內(nèi)部類
// 所以創(chuàng)建對(duì)象時(shí)要通過(guò)外部類來(lái)創(chuàng)建
// 步驟3:通過(guò) 消息構(gòu)造器 創(chuàng)建 消息類 對(duì)象
Demo.Person person = personBuilder.build();
// 步驟4:序列化和反序列化消息(兩種方式)
/*方式1:直接 序列化 和 反序列化 消息 */
// a.序列化
byte[] byteArray1 = person.toByteArray();
// 把 person消息類對(duì)象 序列化為 byte[]字節(jié)數(shù)組
System.out.println(Arrays.toString(byteArray1));
// 查看序列化后的字節(jié)流
// b.反序列化
try {
Demo.Person person_Request = Demo.Person.parseFrom(byteArray1);
// 當(dāng)接收到字節(jié)數(shù)組byte[] 反序列化為 person消息類對(duì)象
System.out.println(person_Request.getName());
System.out.println(person_Request.getId());
System.out.println(person_Request.getEmail());
// 輸出反序列化后的消息
} catch (IOException e) {
e.printStackTrace();
}
/*方式2:通過(guò)輸入/ 輸出流(如網(wǎng)絡(luò)輸出流) 序列化和反序列化消息 */
// a.序列化
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
person.writeTo(output);
// 將消息序列化 并寫入 輸出流(此處用 ByteArrayOutputStream 代替)
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray = output.toByteArray();
// 通過(guò) 輸出流 轉(zhuǎn)化成二進(jìn)制字節(jié)流
// b. 反序列化
ByteArrayInputStream input = new ByteArrayInputStream(byteArray);
// 通過(guò) 輸入流 接收消息流(此處用 ByteArrayInputStream 代替)
try {
Demo.Person person_Request = Demo.Person.parseFrom(input);
// 通過(guò)輸入流 反序列化 消息
System.out.println(person_Request.getName());
System.out.println(person_Request.getId());
System.out.println(person_Request.getEmail());
// 輸出消息
} catch (IOException e) {
e.printStackTrace();
}
}
}
Demo 地址
Carson_Ho的Github :https://github.com/Carson-Ho/ProtocolBuffer
高級(jí)功能
- 貼心的Google還提供將
Protocol Buff
編碼方式 轉(zhuǎn)化為 其他編碼方式,如Json
裹粤、XML
等等
即將
Protocol Buff
對(duì)象 轉(zhuǎn)化為其他編碼方式的數(shù)據(jù)存儲(chǔ)對(duì)象
- 下面展示的是 將
Protocol Buff
對(duì)象 轉(zhuǎn)化為Json
對(duì)象
// 步驟1:在Gradle加入依賴
compile 'com.googlecode.protobuf-java-format:protobuf-java-format:1.4'
// 步驟2:將`Protocol Buff` 對(duì)象 序列化 為 `Json`對(duì)象
JsonFormat jsonFormat = new JsonFormat();
String person2json = jsonFormat.printToString(mProtoBuffer);
至此终蒂, 關(guān)于Protocol Buffer
的使用講解完畢。
7. 總結(jié)
- 看完本文,你應(yīng)該非常了解
Protocol Buffer
在Android
平臺(tái)的使用 -
Carson帶你學(xué)序列化Protocol Buffer系列文章
快來(lái)看看Google出品的Protocol Buffer拇泣,別只會(huì)用Json和XML了
Carson帶你學(xué)序列化:手把手教你如何安裝Protocol Buffer
Carson帶你學(xué)序列化:全面詳解ProtocolBuffer語(yǔ)法
Carson帶你學(xué)序列化:Google出品的序列化神器Protocol Buffer使用指南
Carson帶你學(xué)序列化:Protocol Buffer序列化原理大揭秘-為什么性能這么好噪叙?
Carson帶你學(xué)序列化:深入源碼分析Protocol Buffer
Carson帶你學(xué)序列化:深入分析JSON多種解析方式(Gson、AS自帶org.json霉翔、Jackson)
Carson帶你學(xué)序列化:深入分析XML多種解析方式(DOM睁蕾、SAX、PULL)
歡迎關(guān)注Carson_Ho的簡(jiǎn)書
不定期分享關(guān)于安卓開發(fā)的干貨债朵,追求短子眶、平、快序芦,但卻不缺深度臭杰。