from:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0831/3395.html

編輯推薦:稀土掘金,這是一個針對技術開發者的一個應用,你可以在掘金上獲取最新最優質的技術干貨,不僅僅是Android知識、前端、后端以至于產品和設計都有涉獵,想成為全棧工程師的朋友不要錯過!

原文:http://www.csdn.net/article/2015-08-31/2825579 

JSON——大家可能都知道它是幾乎所有現代服務器都使用的輕量級數據交換格式。它體量輕,可讀性強,通常比老式的、不友好的XML開發起來更加便捷友好。JSON是不依賴于開發語言的數據格式,但是在解析數據并將其轉換到如Java對象時,會消耗我們的時間和存儲資源。

幾天前,Facebook宣布,其Android應用程序大幅提升了數據處理性能。這是由于幾乎在全部應用程序中放棄了JSON數據格式,用FlatBuffers取而代之了。閱讀這篇文章可以獲得關于FlatBuffers的基礎知識,學會如何從JSON轉換到FlatBuffers。

雖然這東西是非常有前景的,但是乍一看其實現過程不是一下子就能明白的。而且Facebook也沒有說得很詳細。這就是為什么我要寫這篇文章,在其中展示我們是如何使用Flatbuffers開展工作的。

FlatBuffers

總之,FlatBuffers是Google專門為游戲開發而創建的跨平臺序列化庫,就像Facebook所展示的那樣,它在Android平臺上遵循快速響應UI的16ms規則

但是,在把所有數據遷移到FlatBuffers之前,你要確定確實需要這樣做。因為,這樣做有時對性能的影響是潛移默化的,而且數據安全性要比計算速度上幾十毫秒的差異更重要。

什么使得Flatbuffers如此奏效?


  • 由于是以二進制形式緩存,訪問序列化數據時也無需數據解析過程。即使對于層次化數據也不需要解析。多虧不需要初始化解析器(初始化意味著要建立復雜的字段映射)和解析數據,這些都是需要花費時間的。

  • Flatbuffers數據不需要分配比自身使用緩沖區還要多的內存。我們不必像在JSON中那樣為解析數據的整個層次分配額外對象。

要獲得正宗的數據,就再讀一讀Facebook上關于FlatBuffers遷移問題的文章,還有Google自己的文檔。


實現

本文將介紹在Android應用程序中使用Flatbuffers的最簡單方法:


  • JSON數據在應用程序之外的某個地方被轉換成FlatBuffer格式的文件(例如,將二進制數據以文件的形式提交,還可以從API直接返回FlatBuffer二進制文件)。

  • 在flatc (FlatBuffer編譯器)的幫助下,手工生成數據模型(Java類)。

  • JSON文件存在一定的局限性(不能使用null字段,日期格式也被解析為字符串)。


將來,我們或許會提出更復雜的解決方案。

FlatBuffers編譯器

首先,我們需要flatc,即flatbuffers編譯器。該編譯器可以從Google所屬的源代碼構建,源代碼位于Flatbuffers資源庫中。我們下載并克隆它。整個構建過程在FlatBuffers構建文檔中都做了描述。如果你是Mac用戶的話,需要這樣來構建:


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

  2. 點擊Play按鈕或⌘ + R,運行flatc scheme(默認情況下應該是被選中的)。

  3. flatc可執行文件就會在項目的根目錄下出現。


現在,我們可以使用schema編譯器了,該編譯器能夠把給定的schema(在Java、C#、Python、GO和C++語言中的schema)生成為模型類,還可以把JSON轉換成Flatbuffer的二進制文件。

Schema文件

接著,我們必須準備schema文件,該文件定義了要進行序列化和反序列化的數據結構。這個schema將用于flatc創建Java模型,把JSON轉換成FlatBuffers的二進制文件。

這里是JSON文件的一部分。

完整版本在這里。這是略微修改后的版本,可以從Github API調用:https://api.github.com/users/google/repos 。

Flatbuffer schema是編寫得很好的文檔,所以就不深入探討這個問題了。另外,本文中的schema不會很復雜。我們所要做的僅僅是創建3張表:ReposList, Repo和User,并定義root_type。這是schema的重要組成部分。

完整的schema文件在這里

FlatBuffers數據文件

真棒,我們現在要做的是把repos_json.json轉換成FlatBuffers二進制文件,生成能夠以Java風格表示數據的Java模型(此處操作所需的全部文件都在我們的代碼庫中):

$ ./flatc -j -b repos_schema.fbs repos_json.json

如果一切順利,會產生下列文件:


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

  • Repos/Repo.java

  • Repos/ReposList.java

  • Repos/User.java


Android應用程序

現在來創建示例程序,在實踐中來看看Flatbuffers格式是如何起作用的。這是截圖:

blob.png

在UI部分,ProgressBar僅用于顯示不恰當的數據處理對用戶界面順暢度的影響。

應用文件看起來是這個樣子:app/build.gradle

當然,在本例中不是必須要用Rx或ButterKnife這樣的視圖注入利器,但是為什么不讓應用更細致一些呢??

我們把repos_flat.bin 和 repos_json.json文件放到res/raw/目錄下。RawDataReader是工具類,它幫助我們讀取Android應用中的原始文件。

最后,把Repo,ReposList和User這三張表對應的模型類代碼放到項目源代碼中。

FlatBuffers庫

使用Java語言編程過程中,FlatBuffers提供了可以直接處理這種數據格式的庫,也這是flatbuffers-java-1.2.0-SNAPSHOT.jar文件。如果你想手工生成該文件,需要下載FlatBuffers源代碼,再到目錄java/下,用Maven生成該庫:

$ mvn install

現在將.jar文件放到Android項目的app/libs/目錄下。

好了,當務之急是實現MainActivity類,這是完整源代碼。

我們最為關注的兩個方法是:


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

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


使用FlatBuffers的結果

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

加載時間

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


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

  • 使用FlatBuffers:FlatBuffers二進制文件(大小:352kB)平均加載時間5ms(時間區間:3ms~10ms)。


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

JSON數據加載效果:

json.gif

FlatBuffers數據加載效果:

flatbuffers.gif

看出區別了嗎?JSON數據的加載過程中, ProgressBar停頓了一會,界面不是那么順暢(加載時間超過了16ms)。

內存分配、CPU等資源

還有什么想要測量的嗎?也許應該測量一下Android Studio 1.3,還有那些新特性。例如,內存分配跟蹤器(Allocation Tracker),內存狀態查看器(Memory Viewer)和方法跟蹤器(Method Tracer)。

源代碼

這里所講解項目的完整源代碼都在Github代碼庫中。你不需要接觸整個FlatBuffers項目,所需的內容全都在flatbuffers/目錄下。

( 翻譯/張揮戈  友情審校/白云鵬)

文章來源:froger_mcs dev blog

作者簡介:

Miroslaw Stanek,Azimo Money Transfer公司移動項目負責人,Android和iOS平臺程序員,視頻游戲玩家,冰雪運動愛好者。個人博客:http://frogermcs.github.io