from:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0831/3395.html
編輯推薦:稀土掘金,這是一個針對技術(shù)開發(fā)者的一個應(yīng)用,你可以在掘金上獲取最新最優(yōu)質(zhì)的技術(shù)干貨,不僅僅是Android知識、前端、后端以至于產(chǎn)品和設(shè)計都有涉獵,想成為全棧工程師的朋友不要錯過!
原文:http://www.csdn.net/article/2015-08-31/2825579
JSON——大家可能都知道它是幾乎所有現(xiàn)代服務(wù)器都使用的輕量級數(shù)據(jù)交換格式。它體量輕,可讀性強(qiáng),通常比老式的、不友好的XML開發(fā)起來更加便捷友好。JSON是不依賴于開發(fā)語言的數(shù)據(jù)格式,但是在解析數(shù)據(jù)并將其轉(zhuǎn)換到如Java對象時,會消耗我們的時間和存儲資源。
幾天前,F(xiàn)acebook宣布,其Android應(yīng)用程序大幅提升了數(shù)據(jù)處理性能。這是由于幾乎在全部應(yīng)用程序中放棄了JSON數(shù)據(jù)格式,用FlatBuffers取而代之了。閱讀這篇文章可以獲得關(guān)于FlatBuffers的基礎(chǔ)知識,學(xué)會如何從JSON轉(zhuǎn)換到FlatBuffers。
雖然這東西是非常有前景的,但是乍一看其實(shí)現(xiàn)過程不是一下子就能明白的。而且Facebook也沒有說得很詳細(xì)。這就是為什么我要寫這篇文章,在其中展示我們是如何使用Flatbuffers開展工作的。
FlatBuffers
總之,FlatBuffers是Google專門為游戲開發(fā)而創(chuàng)建的跨平臺序列化庫,就像Facebook所展示的那樣,它在Android平臺上遵循快速響應(yīng)UI的16ms規(guī)則。
但是,在把所有數(shù)據(jù)遷移到FlatBuffers之前,你要確定確實(shí)需要這樣做。因為,這樣做有時對性能的影響是潛移默化的,而且數(shù)據(jù)安全性要比計算速度上幾十毫秒的差異更重要。
什么使得Flatbuffers如此奏效?
由于是以二進(jìn)制形式緩存,訪問序列化數(shù)據(jù)時也無需數(shù)據(jù)解析過程。即使對于層次化數(shù)據(jù)也不需要解析。多虧不需要初始化解析器(初始化意味著要建立復(fù)雜的字段映射)和解析數(shù)據(jù),這些都是需要花費(fèi)時間的。
Flatbuffers數(shù)據(jù)不需要分配比自身使用緩沖區(qū)還要多的內(nèi)存。我們不必像在JSON中那樣為解析數(shù)據(jù)的整個層次分配額外對象。
要獲得正宗的數(shù)據(jù),就再讀一讀Facebook上關(guān)于FlatBuffers遷移問題的文章,還有Google自己的文檔。
實(shí)現(xiàn)
本文將介紹在Android應(yīng)用程序中使用Flatbuffers的最簡單方法:
JSON數(shù)據(jù)在應(yīng)用程序之外的某個地方被轉(zhuǎn)換成FlatBuffer格式的文件(例如,將二進(jìn)制數(shù)據(jù)以文件的形式提交,還可以從API直接返回FlatBuffer二進(jìn)制文件)。
在flatc (FlatBuffer編譯器)的幫助下,手工生成數(shù)據(jù)模型(Java類)。
JSON文件存在一定的局限性(不能使用null字段,日期格式也被解析為字符串)。
將來,我們或許會提出更復(fù)雜的解決方案。
FlatBuffers編譯器
首先,我們需要flatc,即flatbuffers編譯器。該編譯器可以從Google所屬的源代碼構(gòu)建,源代碼位于Flatbuffers資源庫中。我們下載并克隆它。整個構(gòu)建過程在FlatBuffers構(gòu)建文檔中都做了描述。如果你是Mac用戶的話,需要這樣來構(gòu)建:
在\{extract directory}\build\XcodeFlatBuffers.xcodeproj路徑下,打開已下載的源代碼。
點(diǎn)擊Play按鈕或⌘ + R,運(yùn)行flatc scheme(默認(rèn)情況下應(yīng)該是被選中的)。
flatc可執(zhí)行文件就會在項目的根目錄下出現(xiàn)。
現(xiàn)在,我們可以使用schema編譯器了,該編譯器能夠把給定的schema(在Java、C#、Python、GO和C++語言中的schema)生成為模型類,還可以把JSON轉(zhuǎn)換成Flatbuffer的二進(jìn)制文件。
Schema文件
接著,我們必須準(zhǔn)備schema文件,該文件定義了要進(jìn)行序列化和反序列化的數(shù)據(jù)結(jié)構(gòu)。這個schema將用于flatc創(chuàng)建Java模型,把JSON轉(zhuǎn)換成FlatBuffers的二進(jìn)制文件。
這里是JSON文件的一部分。
完整版本在這里。這是略微修改后的版本,可以從Github API調(diào)用:https://api.github.com/users/google/repos 。
Flatbuffer schema是編寫得很好的文檔,所以就不深入探討這個問題了。另外,本文中的schema不會很復(fù)雜。我們所要做的僅僅是創(chuàng)建3張表:ReposList, Repo和User,并定義root_type。這是schema的重要組成部分。
完整的schema文件在這里。
FlatBuffers數(shù)據(jù)文件
真棒,我們現(xiàn)在要做的是把repos_json.json轉(zhuǎn)換成FlatBuffers二進(jìn)制文件,生成能夠以Java風(fēng)格表示數(shù)據(jù)的Java模型(此處操作所需的全部文件都在我們的代碼庫中):
$ ./flatc -j -b repos_schema.fbs repos_json.json
如果一切順利,會產(chǎn)生下列文件:
Android應(yīng)用程序
現(xiàn)在來創(chuàng)建示例程序,在實(shí)踐中來看看Flatbuffers格式是如何起作用的。這是截圖:

在UI部分,ProgressBar僅用于顯示不恰當(dāng)?shù)臄?shù)據(jù)處理對用戶界面順暢度的影響。
應(yīng)用文件看起來是這個樣子:app/build.gradle
當(dāng)然,在本例中不是必須要用Rx或ButterKnife這樣的視圖注入利器,但是為什么不讓應(yīng)用更細(xì)致一些呢??
我們把repos_flat.bin 和 repos_json.json文件放到res/raw/目錄下。RawDataReader是工具類,它幫助我們讀取Android應(yīng)用中的原始文件。
最后,把Repo,ReposList和User這三張表對應(yīng)的模型類代碼放到項目源代碼中。
FlatBuffers庫
使用Java語言編程過程中,F(xiàn)latBuffers提供了可以直接處理這種數(shù)據(jù)格式的庫,也這是flatbuffers-java-1.2.0-SNAPSHOT.jar文件。如果你想手工生成該文件,需要下載FlatBuffers源代碼,再到目錄java/下,用Maven生成該庫:
$ mvn install
現(xiàn)在將.jar文件放到Android項目的app/libs/目錄下。
好了,當(dāng)務(wù)之急是實(shí)現(xiàn)MainActivity類,這是完整源代碼。
我們最為關(guān)注的兩個方法是:
使用FlatBuffers的結(jié)果
現(xiàn)在讓我們把JSON和FlatBuffers在加載時間和資源消耗方面的差異形象化。測試是在帶有Android M(beta版)的Nexus 5上進(jìn)行的。
加載時間
測量的過程是將其他文件轉(zhuǎn)換為Java源文件,對所有(90個)元素進(jìn)行迭代。
記得16ms規(guī)則嗎?我們在UI線程中調(diào)用這些方法的原因就是要看看在這種情況下界面表現(xiàn)如何:
JSON數(shù)據(jù)加載效果:

FlatBuffers數(shù)據(jù)加載效果:

看出區(qū)別了嗎?JSON數(shù)據(jù)的加載過程中, ProgressBar停頓了一會,界面不是那么順暢(加載時間超過了16ms)。
內(nèi)存分配、CPU等資源
還有什么想要測量的嗎?也許應(yīng)該測量一下Android Studio 1.3,還有那些新特性。例如,內(nèi)存分配跟蹤器(Allocation Tracker),內(nèi)存狀態(tài)查看器(Memory Viewer)和方法跟蹤器(Method Tracer)。
源代碼
這里所講解項目的完整源代碼都在Github代碼庫中。你不需要接觸整個FlatBuffers項目,所需的內(nèi)容全都在flatbuffers/目錄下。
( 翻譯/張揮戈 友情審校/白云鵬)
文章來源:froger_mcs dev blog
作者簡介:
Miroslaw Stanek,Azimo Money Transfer公司移動項目負(fù)責(zé)人,Android和iOS平臺程序員,視頻游戲玩家,冰雪運(yùn)動愛好者。個人博客:http://frogermcs.github.io。