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)建:


  1. 在\{extract directory}\build\XcodeFlatBuffers.xcodeproj路徑下,打開已下載的源代碼。

  2. 點(diǎn)擊Play按鈕或⌘ + R,運(yùn)行flatc scheme(默認(rèn)情況下應(yīng)該是被選中的)。

  3. 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)生下列文件:


  • repos_json.bin(要將重命名它為 repos_flat.bin)

  • Repos/Repo.java

  • Repos/ReposList.java

  • Repos/User.java


Android應(yīng)用程序

現(xiàn)在來創(chuàng)建示例程序,在實(shí)踐中來看看Flatbuffers格式是如何起作用的。這是截圖:

blob.png

在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)注的兩個方法是:


  • parseReposListJson(String reposStr) - 這個方法初始化Gson解析器,并把JSON字符串轉(zhuǎn)換成Java對象。

  • loadFlatBuffer(byte[] bytes)  - 這個方法將字節(jié)(repos_flat.bin文件)轉(zhuǎn)換成Java對象。


使用FlatBuffers的結(jié)果

現(xiàn)在讓我們把JSON和FlatBuffers在加載時間和資源消耗方面的差異形象化。測試是在帶有Android M(beta版)的Nexus 5上進(jìn)行的。

加載時間

測量的過程是將其他文件轉(zhuǎn)換為Java源文件,對所有(90個)元素進(jìn)行迭代。


  • 使用JSON:JSON文件(大小:478kB)平均加載時間200ms(時間區(qū)間:180ms~250ms);

  • 使用FlatBuffers:FlatBuffers二進(jìn)制文件(大?。?52kB)平均加載時間5ms(時間區(qū)間:3ms~10ms)。


記得16ms規(guī)則嗎?我們在UI線程中調(diào)用這些方法的原因就是要看看在這種情況下界面表現(xiàn)如何:

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

json.gif

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

flatbuffers.gif

看出區(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。