編輯:開發入門
XMLvsJSON 應用程序
需要注意的是,樣例應用程序沒有實時地從 web 移動數據,盡管我們期盼一個真實應用程序。由於數據 feeds 取自原始資源文件夾,因此應用程序關注的是分析方面。關於使用 android 進行網絡連接相關信息的鏈接,見 參考資料。
android 應用程序很簡單。其中包含 XML 和 JSON 數據資料的全部副本。用戶可以任選其一進行分析。 圖 2 顯示 Eclipse 中項目文件的結構。(查看 圖 2 的文本版本。)
圖 2. Eclipse 項目的文件結構
圖 3 顯示選擇解析選項之前的應用程序 UI:
圖 3. 選擇解析選項之前的應用程序 UI
應用程序 UI 有兩個按鈕,Parse XML 和 Parse JSON,接著是默認文本。清單 6 包含該 UI 的布局,在項目的 res/layout 文件夾中的 main.XML 中可以找到:
清單 6. UI 的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orIEntation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnXML" android:text="Parse XML"></Button> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnJSON" android:text="Parse JSON file"></Button> </LinearLayout> <ScrollVIEw XMLns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ScrollView01" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextVIEw android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="default text" android:layout_gravity="center_horizontal" android:id="@+id/txtData" /> </ScrollVIEw> </LinearLayout>
Parse XML 和 Parse JSON file 按鈕是在 ScrollVIEw
之上定義的,ScrollVIEw
中含有一個 TextVIEw
控件。這裡的意思是想要用戶可以滾動結果數據。
注意多個 LinearLayout
結構的使用。第一個是垂直對齊,其中既含有一個帶有水平結構的 LinearLayout
和一個 ScrollVIEw
。內層LinearLayout
含有兩個 Button
小部件。這個布局很冗長,一般在onCreate()
方法中調用,見 清單 7:
清單 7. onCreate()
方法
Button btnXML; Button btnJSON; TextView tvData; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tvData = (TextView) findViewById(R.id.txtData); btnXML = (Button) findViewById(R.id.btnXML); btnXML.setOnClickListener(new Button.OnClickListener() { public void onClick(VIEw v) { examineXMLFile(); } }); btnJSON = (Button) findViewById(R.id.btnJSON); btnJSON.setOnClickListener(new Button.OnClickListener() { public void onClick(VIEw v) { examineJSONFile(); } }); }
examineXMLFile()
方法控制 XML 解析。
回頁首
XML 解析
android 也支持一個 DOM 解析器,這需要占用較大的內存空間,但是降低在 SAX 解析器中的復雜性。對於 XMLvsJSON 這個應用程序,僅僅對大數據資源很小的一個子集感興趣,SAX 方法可能是處理作業的最好工具。
XML 數據解析通常是使用一個 SAX 風格的解析器完成的。對於這類解析器,您可以建立一個 InputSource
指向源 XML 數據,並在文檔 “運行” 時提供一個接收某些事件的處理程序。清單 8 展示examineXMLFile()
方法,執行以下任務:
InputSource
SAXParser
,關聯處理程序 twitterFeedHandler
(見 清單 9)
TextVIEw
小部件中顯示結果,在布局文件中作為R.id.txtData
識別,在代碼中作為 tvData
引用
TextVIEw
中
清單 8. examineXMLFIle()
方法
void examineXMLFile() { try { InputSource is = new InputSource(getResources() .openRawResource(R.raw.xmltwitter)); // create the factory SAXParserFactory factory = SAXParserFactory.newInstance(); // create a parser SAXParser parser = factory.newSAXParser(); // create the reader (scanner) XMLReader xmlreader = parser.getXMLReader(); // instantiate our handler twitterFeedHandler tfh = new twitterFeedHandler(); // assign our handler xmlreader.setContentHandler(tfh); // perform the synchronous parse XMLreader.parse(is); // should be done... let's display our results tvData.setText(tfh.getResults()); } catch (Exception e) { tvData.setText(e.getMessage()); } }
雖然 examineXMLFile()
設置好了一切,但應用程序角度來看,真正的解析工作實際是在處理程序中進行的,該處理程序是在 twitterFeedHandler.Java 文件中實現的。實現 DefaultHandler
接口的類見 清單 9:
清單 9. twitterFeedHandler
類
public class twitterFeedHandler extends DefaultHandler { StringBuilder sb = null; String ret = ""; boolean bStore = false; int howMany = 0; twitterFeedHandler() { } String getResults() { return "XML parsed data.\nThere are [" + howMany + "] status updates\n\n" + ret; } @Override public void startDocument() throws SAXException { // initialize "list" } @Override public void endDocument() throws SAXException { } @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { try { if (localName.equals("status")) { this.sb = new StringBuilder(""); bStore = true; } if (localName.equals("user")) { bStore = false; } if (localName.equals("text")) { this.sb = new StringBuilder(""); } if (localName.equals("created_at")) { this.sb = new StringBuilder(""); } } catch (Exception ee) { Log.d("error in startElement", ee.getStackTrace().toString()); } } @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException { if (bStore) { if (localName.equals("created_at")) { ret += "Date: " + sb.toString() + "\n"; sb = new StringBuilder(""); return; } if (localName.equals("user")) { bStore = true; } if (localName.equals("text")) { ret += "Post: " + sb.toString() + "\n\n"; sb = new StringBuilder(""); return; } } if (localName.equals("status")) { howMany++; bStore = false; } } @Override public void characters(char ch[], int start, int length) { if (bStore) { String theString = new String(ch, start, length); this.sb.append(theString); } } }
清單 9 中有一些值得注意的細節,首先考慮到的是 SAX 解析器是一個基於事件的解析器,這就意味著使用 SAX 進行解析時要建立真實文件。在文檔開始和結束、標記開始和結束、發現數據時,事件被觸發。這意味著您必須定義一個數據結構來保留感興趣的數據、拋棄余下的。
注意,使用 StringBuilder
和附加數據是因為一個特定數據在InputSource
上能通過多個讀取來進行處理。千萬不要以為所有數據都在給定的調用 characters()
方法中提供。
應用程序將數據收集到一個簡單的格式化字符串中。而另一個示例中則是把這些實體放在一個集合類或數據庫中,特別是如果有大量的操作都發生在解析之後。
getResults()
方法是該類特有的,用來收集這類數據的集中表示法,並將其提供給應用程序,這不是 DefaultHandler
接口的一部分。
圖 4 展示了已解析的 XML 數據。(查看 圖 4 的文本版本。)
圖 4. 已解析的 XML 數據
盡管從構建、管理和導航結果結構方面來說,使用 SAX 解析器解析 XML 數據並不容易,但其主要優勢是快速和極大地減少了解析過程中和解析之後的 RAM 需求數量。
現在看一下 android 解析 JSON 數據的方法。
回頁首
JSON 解析
在用戶選擇 JSON 按鈕時解析 JSON 數據就開始了。調用examineJSONFile()
方法,如 清單 10 所示。不需要額外的處理類。因為所有解析和文檔管理都在 android 提供的庫中進行,所有 JSON 相關的代碼都包含在這個方法中。
清單 10. 調用 examineJSONfile()
方法
void examineJSONFile() { try { String x = ""; InputStream is = this.getResources().openRawResource(R.raw.jsontwitter); byte [] buffer = new byte[is.available()]; while (is.read(buffer) != -1); String jsontext = new String(buffer); JSONArray entries = new JSONArray(jsontext); x = "JSON parsed.\nThere are [" + entries.length() + "]\n\n"; int i; for (i=0;i<entries.length();i++) { JSONObject post = entrIEs.getJSONObject(i); x += "------------\n"; x += "Date:" + post.getString("created_at") + "\n"; x += "Post:" + post.getString("text") + "\n\n"; } tvData.setText(x); } catch (Exception je) { tvData.setText("Error w/file: " + je.getMessage()); } }
像之前顯示的 XML 例程一樣,代碼是從原始資源文件夾的文件中讀取的。數據被整體讀到內存中,轉換成一個 Java.lang.String
,然後解析成 JSONArray
。要注意的是,正如此例所示,一個特殊的字符串能直接解析成一個數組,或者也可以直接解析成一個JSONObject
。因為 Twitter 數據是一個對象數組,整體解析成一個數組然後按順序逐個訪問對象是明智的選擇。
該方法的流程簡單明了,一旦數據被解析,代碼建立一個類似於 XML 解析器處理程序方法的字符串表示。有趣的是數據將由您來管理;您不需要建立額外內存結構來容納數據,同樣地,應用程序預先就知道在 JSONArray
中有多少個條目(在這個例子中是 20 個)。
盡管 JSON 解析在編程上簡單得多,但並不是沒有代價的。它要增加內存消耗,在處理之前整體讀取數據流並進行存儲。相反的,SAX XML 方法僅使用相關數據。另外,如果解析特殊 JSON 對象的內存是足夠的,則這個方法將很受應用程序歡迎,特別是,幾乎不需要使用 DOM 的應用程序。
結束語
本文在 android 應用程序背景下介紹了 XML 和 JSON 數據交換格式。比起 JSON 方法,XML 方法更快、內存受限更小 — 但是以增加復雜性為代價。在第二部分,我將介紹一些結合使用 JSON 方法的先進技術,例如,基於 WebKit 的 WebVIEw 小部件,並為 android 應用程序定制動態應用程序邏輯。
Android 應用程序必須訪問位於 Internet 上的數據,而 Internet 數據可以有幾種不同的格式。本文將介紹在 android 應用程序中如何使用三種數
1,基本環境准備:安裝JDK1.5以上,Eclipse3.3以上版本.(MyEclipse也可以),筆者安裝了JDK1.6和MyEclipse 8.6。JDK1.6My
使用 listVIEw 小部件:一個簡單的樣例應用程序在本部分中,我們將創建一個樣例應用程序(見圖 9a,9b)來使用listVIEw 小部件顯示電話簿中的所
連接 JavaScript 接口下一步是啟用 Activity 中的 Java 代碼,以與 WebVIEw 管理的 Html 文件中的 JavaScript 代碼交互。