Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 開發入門 >> 在 Android 上使用 XML 和 JSON,第 1 部分: 在 Android 應用程序上研究 JSON 和 XML 益處(二)

在 Android 上使用 XML 和 JSON,第 1 部分: 在 Android 應用程序上研究 JSON 和 XML 益處(二)

編輯:開發入門

XMLvsJSON 應用程序

真實的實時更新

需要注意的是,樣例應用程序沒有實時地從 web 移動數據,盡管我們期盼一個真實應用程序。由於數據 feeds 取自原始資源文件夾,因此應用程序關注的是分析方面。關於使用 android 進行網絡連接相關信息的鏈接,見 參考資料

android 應用程序很簡單。其中包含 XML 和 JSON 數據資料的全部副本。用戶可以任選其一進行分析。 圖 2 顯示 Eclipse 中項目文件的結構。(查看 圖 2 的文本版本。)


圖 2. Eclipse 項目的文件結構
Eclipse 中文件結構的屏幕截圖 
 

圖 3 顯示選擇解析選項之前的應用程序 UI:


圖 3. 選擇解析選項之前的應用程序 UI 
選擇解析選項之前的應用程序 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 解析

SAX 對 DOM

android 也支持一個 DOM 解析器,這需要占用較大的內存空間,但是降低在 SAX 解析器中的復雜性。對於 XMLvsJSON 這個應用程序,僅僅對大數據資源很小的一個子集感興趣,SAX 方法可能是處理作業的最好工具。

XML 數據解析通常是使用一個 SAX 風格的解析器完成的。對於這類解析器,您可以建立一個 InputSource 指向源 XML 數據,並在文檔 “運行” 時提供一個接收某些事件的處理程序。清單 8 展示examineXMLFile() 方法,執行以下任務:

  • 使用原始資料中的 XML 文件建立 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 數據
手機上已解析的 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 應用程序定制動態應用程序邏輯。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved