編輯:開發入門
使用 JSON
XML 是 android 上的一等公民,鑒於依賴於 XML 的 Web 服務的數量,這是個好事。很多服務還支持另一個流行格式 JSON。它通常比 XML 簡潔一些,但也是人們可讀的,使得它更易於使用,並且可以更輕松地將其用於調試使用它的應用程序。android 包括一個 JSON 解析器。(您可以從 JSON.org 網站獲得該解析器,只是要去除幾個手機不需要的類)。 清單 9 顯示了使用中的解析器:
清單 9. JSON 解析器實現
private class StockJsonParser extends BaseStockParser{ public StockJsonParser(){ super("json"); } @Override protected Stock[] doInBackground(String... symbols) { Stock[] stocks = new Stock[symbols.length]; try{ StringBuilder json = new StringBuilder(); BufferedReader reader = new BufferedReader( new InputStreamReader(getData(symbols))); String line = reader.readLine(); while (line != null){ json.append(line); line = reader.readLine(); } JSONObject jsonObj = new JSONObject(json.toString()); JSONArray stockArray = jsonObj.getJSONArray("stocks"); for (int i=0;i<stocks.length;i++){ JSONObject object = stockArray.getJSONObject(i).getJSONObject("stock"); stocks[i] = new Stock(object.getString("symbol"), object.getString("name"), object.getDouble("price")); } } catch (Exception e){ Log.e("DayTrader", "Exception getting JSON data", e); } return stocks; } }
可以看到在 android 中使用 JSON 解析器是多麼簡單。您將來自服務器的流轉換成傳遞給 JSON 解析器的字符串。您遍歷對象圖並創建Stock
對象數組。如果使用過 XML DOM 解析,這看起來很類似,因為編程模型幾乎一樣。
像 DOM 一樣,JSON 解析器可以用於內存密集型應用。在 清單 9中,所有來自服務器的數據都表示為字符串,然後作為JSONObject
,最後作為 Stock
對象數組。換句話說,同一數據通過三種不同的方式表示。可以看到,對於大量數據而言,這可能是個問題。當然,一旦到達方法末尾,這三種數據表示方式中的兩種都會落在范圍之外,被垃圾回收器回收。但是,只是觸發更頻繁的垃圾回收可能會對用戶體驗帶來負面影響,造成處理速度下降。如果內存效率和性能很重要,使用 protocol buffers 的解析器可能是個較好的選擇。
使用 protocol buffers 處理二進制
Protocol buffers 是一個由 Google 開發的與語言無關的數據串行化格式,旨在比 XML 更快地通過網絡傳送數據。它是 Google 用於服務器對服務器調用的事實 標准。Google 將該格式及其用於 C++、Java 和 Python 編程語言的綁定工具以開源方式提供。
在 清單 3 和 清單 6 中看到 protocol buffers 是二進制格式。如您所料,這使得數據很簡潔。如果在客戶端和服務器端啟用 gzip 壓縮,在使用 XML 和 JSON 時通常也可以得到類似的消息大小,但是 protocol buffers 仍然有一些大小上的優勢。它還是一種可以迅速解析的格式。最後,它提供了一個相當簡單的 API。 清單 10 顯示了一個示例解析器實現:
清單 10. Protocol buffers 解析器實現
private class StockProtoBufParser extends BaseStockParser{ public StockProtoBufParser(){ super("protobuf"); } @Override protected Stock[] doInBackground(String... symbols) { Stock[] stocks = new Stock[symbols.length]; try{ Stocks.Portfolio portfolio = Stocks.Portfolio.parseFrom(getData(symbols)); for (int i=0;i<symbols.length;i++){ stocks[i] = Stock.fromQuote(portfolio.getQuote(i)); } } catch (Exception e){ Log.e("DayTrader", "Exception getting ProtocolBuffer data", e); } return stocks; } }
如 清單 3 所示,您可以使用 protocol buffers 編譯器生成的 helper 類。這與服務器使用的 helper 類相同。可以編譯它一次,然後在服務器和客戶端共享它。 這樣,您可以更輕松地直接從服務器的流讀取數據並將其轉換成 Stock
對象數組。這種簡單編程也具有非常出色的性能。現在看一下此性能與 XML 和 JSON 的比較。
性能比較
比較性能通常涉及某種微基准測試,此類基准測試很容易產生偏見或無意間得到不正確的結果。即使以公平方式設計微基准測試,很多隨機因素也會對結果產生影響。盡管有這些問題,我還是要使用這樣的微基准測試來比較 XML(大約 1300 ms)、JSON(大約 1150 ms)和 protocol buffers(大約 750 ms)。基准測試向服務器發送了一個關於 200 個股票的請求並測量了從發出請求到用於創建 ListVIEw
的 Adapter
的數據准備就緒所需的時間量。對每個數據格式在兩個設備上進行 50 次這樣的操作:一個 Motorola Droid 和一個 HTC Evo,兩個都通過 3G 網絡。 圖 2 顯示了結果:
圖 2. 比較數據格式速度
圖 2 顯示出,在此基准測試中 protocol buffers(大約 750 ms)比 XML (大約 1300 ms)幾乎快兩倍。很多因素影響著數據通過網絡和被手持設備處理的性能。一個明顯的因素是通過網絡的數據量。二進制格式的 protocol buffers 比文本格式的 XML 和 JSON 在通過網絡時小得多。然而,文本格式可以使用 gzip 進行有效地壓縮,這是 Web 服務器和 android 設備都支持的標准技術。 圖 3 顯示了在打開和關閉 gzip 時通過網絡的數據大小:
圖 3. 不同格式的數據大小
圖 3 應該增加了您對 XML 和 JSON 之類的文本內容的壓縮效果的喜愛(更不用說 Web 格式、Html、JavaScript 和 CSS 了)。protocol buffers 數據(大約 6KB)比原始 XML(大約 17.5KB)或 JSON(大約 13.5KB)數據小得多。但是一旦進行了壓縮, JSON 和 XML(都是大約 3KB)實際上比 protocol buffers 小很多了。在本例中,它們都接近於 protocol-buffers 編碼消息大小的一半了。
回到 圖 2,速度的不同顯然不能由通過網絡的消息大小解釋。protocol-buffers 消息比 XML 或 JSON 編碼的消息大,但是通過使用 protocol buffers,您仍然能夠削減半秒鐘的用戶等待時間。這是否意味著應該在 android 應用程序中使用 protocol buffers 呢?這樣的決定很少是固定的。如果要發送的數據量很小,則三種格式間的差異也不大。對於大量數據而言,protocol buffers 可能會有所不同。但是,像這樣精心設計的基准測試無法替代對您自己的應用程序的測試。
結束語
本文介紹了如何使用 Internet 上流行的兩種數據格式 XML 和 JSON 的方方面面。還講到了第三種可能性,protocol buffers。像軟件工程中的其他內容一樣,選擇技術主要就是權衡利弊。當您為一個局限的環境(比如 Android)開發時,這些決定的結果往往被放大了。我希望您現在擁有的關於這些後果的額外知識能夠幫助您創建出色的 android 應用程序。
創建內容提供器和 Google Maps 應用程序您已經看到了一個完整的應用程序示例,現在簡要討論一下更加復雜的應用程序。內容提供器和 Google Maps本教程中討
簡介: 這個兩部分文章系列探索了在 android 平台上處理 Internet 上兩種最常見的數據格式 — XML 和 JavaScript Object
跨進程訪問(AIDL服務)android系統中的進程之間不能共享內存,因此,需要提供一些機制在不同進程之間進行數據通信。我們知道4個Android應用程序組件中的3個(
New Message 頁面在 8.0.2 版本中,將針對用戶的個人聯系列表和企業名錄對 ultra-light 模式下發送的消息中的電子郵件地址進行檢查,如果可以的話