Android開發(fā)之在Windows上Protocol Buffer的接入

1 Introduction

Protocol Buffers是在網(wǎng)絡通訊或者數(shù)據(jù)存儲時用到的一種語言無關、平臺無關、可擴展的序列化結構數(shù)據(jù)格式。類似于XML,不過比XML更小、更快、更簡單。
你首先要定義自己想要的數(shù)據(jù)結構(在 .proto 文件中定義數(shù)據(jù)結構信息),經(jīng)過Protocol Buffers 編譯后生成.java代碼文件,就可以根據(jù).java里的數(shù)據(jù)對象來進行讀寫操作。

下面談談在Android開發(fā)中如何接入protocol buffers。

2 JavaNano

protocol buffers支持多種語言環(huán)境下的使用。Java雖然是Android開發(fā)的絕對主流開發(fā)語言,但是protobuf還是針對Android開發(fā)這種性能資源有限的系統(tǒng)專門提供了一個JavaNano版本(而不是直接使用protobuf的Java版本進行編譯),在代碼量和運行時開銷上都比較友好(詳細介紹點這)。

3 Usage

3.1 Defining A Message Type

即編寫.protol文件,通常這部分工作由后臺完成,畢竟是后端來決定在網(wǎng)絡連接中,傳輸什么字段給客戶端或者客戶端提交什么字段給服務器。類似于定義json的字段結構。
示例:

syntax = "proto3";//指定protocol buffer版本

message SearchRequest {//這是一個message的定義,包含了三個屬性,每個屬性有一個字段名和類型
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...//一些字段的定義
}

3.2 What's Generated From Your .proto?

運行protocol buffer 編譯器去編譯.proto文件,可以根據(jù)你選擇的語言生成相應的代碼文件。
編譯Java語言版本的時候,編譯器會為每一個message生成.java類文件,每個類還對應一個Builder提供給開發(fā)者去構建實例。值得注意的是,我們在Android上使用的protobuf JavaNano與protobuf Java相比,去除了一些復雜的特性。比如剛剛提到的Builder,還有Descriptors都被去掉。同時通過直接訪問類的public成員變量的方式取代了set/get方法。

3.3 Compile on Windows

在Windwos上編譯.protol文件十分簡單。

  1. protocol 編譯器是用C++寫的,C++開發(fā)者可以在github google/protobuf下載源碼編譯出來。對于非C++開發(fā)者,也可以直接下載現(xiàn)成的編譯器protoc-3.0.0-beta-3-win32.zip。(這里獲取各個OS下的編譯器。
  2. 解壓下載好的protoc-3.0.0-beta-3-win32.zip,將解壓后的目錄名添加到Windows的PATH環(huán)境變量
  3. 調(diào)出Windows的命令行,輸入protoc --version,出現(xiàn)以下畫面,說明編譯器可以使用了。
    protoc --version
  4. 生成Java類
    protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/message.proto
    上面的$SRC_DIR表示存放message.proto文件的路徑,$DST_DIR表示生成java類存放的路徑。-I=$SRC_DIR可以省略,如果message.proto文件與protoc.exe在同一個目錄下。
    例如:
protoc -I=D:\ --javanano_out=E:\ D:\message.proto
--javanano_out

這里我的message.proto文件放在D盤,指定編譯生成的java類放到E盤。

Message.java

可以看到編譯出來的java類文件已經(jīng)安靜地躺在我的E盤中。這個類就和我們平時使用的Bean類的用法一毛一樣了。

3.4 Compile Options

有一些常用的編譯選項可以在message.proto文件中預先定義:

option java_package = "com.android.develop";  //指定java類的包名
 
option java_multiple_files = true; //message.proto文件中的每個message都生成一個對應的.java。設為fasle時只導出一個.java類文件,所有message都以內(nèi)部類的形式出現(xiàn)
 
option java_outer_classname = "MessageBean";//當只生成一個.java文件時,指定類名, java_multiple_files =true時,這個屬性無效。
 
message SearchRequest {
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message OtherMessages{
.......
}

命令行編譯時,還有以下選項可以用:

  1. optional_field_style={default,accessors,reftypes} (default: default)
    設置成員變量的訪問方式。default就是public直接訪問,accessors就是set/get方法,reftypes使用基本類型的包裝類來定義字段類型(例如Interger代替原本的int,空值為null,可以避免空值==0時的歧義。)。
  2. enum_style={c,java} (default: c)
  3. parcelable_messages={true,false} (default: false)
    開啟了這個選項后,編譯生成的java類自動實現(xiàn)Parcelable接口,最常用的Intent傳值就可以直接使用這些對象。

使用示例:
protoc --javanano_out=optional_field_style=accessors,parcelable_messages=true:d:\ D:\protoc-3.0.0-beta-3-win32\message.proto
這時,編譯出來的java類,就是通過set/get方法訪問private的成員變量,同時也已經(jīng)實現(xiàn)了Parcelable接口。

3.5 The Protocol Buffer API

每一個編譯后生成的protobuf Message類都提供了方法去讀寫二進制格式的數(shù)據(jù)。

  1. byte[] toByteArray();
    序列化message,并返回一個包含了message的原始數(shù)據(jù)的byte數(shù)組。
  2. static SearchRequest parseFrom(byte[] data);
    從一個給定的byte數(shù)組中,反序列化出來一個message對象。
  3. void writeTo(OutputStream output);
    序列化message,并寫到一個OutputStream上。
  4. static SearchRequest parseFrom(InputStream input);
    從一個InputStream讀取并反序列化出message對象。

3.6 Protocol Buffers and O-O Design

官方推薦使用包裝類的形式來對生成的ProtoBuf Message java類進行封裝及擴展,而不是繼承它們。因為繼承并重寫父類方法的時候將會破壞ProtoBuf Message類的內(nèi)在機制。

You should never add behaviour to the generated classes by inheriting from them. This will break internal mechanisms and is not good object-oriented practice anyway.

4 Links

  1. 官方指南
  2. google/protobuf/README.md
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內(nèi)容

  • 由于工程項目中擬采用一種簡便高效的數(shù)據(jù)交換格式,百度了一下發(fā)現(xiàn)除了采用 xml、JSON 還有 ProtoBuf(...
    黃海佳閱讀 48,803評論 1 23
  • 前面翻譯了谷歌的Proto3 語言指南 這一篇講實戰(zhàn)應用先總結一下 Protocol Buffer 一、什么是Pr...
    黃海佳閱讀 4,135評論 1 1
  • 因為https://blog.csdn.net/urdfmqcul2/article/details/787889...
    蘇大盒子閱讀 4,490評論 1 1
  • 0 是整型的0 / 字符的00.0是實數(shù)的0'\0'是字符的0 NULL是指針的0 '0'是字符 的48 asci...
    SmallTwo閱讀 449評論 0 0
  • 昨晚和阿甘小酌了幾瓶啤酒,擼了兩手烤串,絮絮叨叨的講起了許多少年往事,回到酒店房間開了幾局農(nóng)藥,不知是酒量漸虛,還...
    楊小燁閱讀 141評論 0 0