編輯:關於Android編程
? ??XML在各種開發中都廣泛應用,Android也不例外。作為承載數據的一個重要角色,如何讀寫XML成為Android開發中一項重要的技能。今天就由我向大家介紹一下在Android平台下幾種常見的XML解析和創建的方法。
.
(一)SAX解析器:
? ??SAX(Simple API for XML)解析器是一種基於事件的解析器,它的核心是事件處理模式,主要是圍繞著事件源以及事件處理器來工作的。當事件源產生事件後,調用事件處理器相應的處理方法,一個事件就可以得到處理。在事件源調用事件處理器中特定方法的時候,還要傳遞給事件處理器相應事件的狀態信息,這樣事件處理器才能夠根據提供的事件信息來決定自己的行為。
SAX解析器的優點是解析速度快,占用內存少。非常適合在Android移動設備中使用。
.
(二)DOM解析器:
? ??DOM是基於樹形結構的的節點或信息片段的集合,允許開發人員使用DOM API遍歷XML樹、檢索所需數據。分析該結構通常需要加載整個文檔和構造樹形結構,然後才可以檢索和更新節點信息。
由於DOM在內存中以樹形結構存放,因此檢索和更新效率會更高。但是對於特別大的文檔,解析和加載整個文檔將會很耗資源。
.
(三)PULL解析器:
? ??PULL解析器的運行方式和SAX類似,都是基於事件的模式。不同的是,在PULL解析過程中,我們需要自己獲取產生的事件然後做相應的操作,而不像SAX那樣由處理器觸發一種事件的方法,執行我們的代碼。PULL解析器小巧輕便,解析速度快,簡單易用,非常適合在Android移動設備中使用,Android系統內部在解析各種XML時也是用PULL解析器。
以上三種解析器,都是非常實用的解析器,我將會一一介紹。我們將會使用這三種解析技術完成一項共同的任務。
.
.
二.文件解析的實現
.
(一)創建XMl文件
在項目的assets目錄中創建一個XML文檔cars.xml,如圖所示:
.
.
雙擊打開xml文件,編輯內容如下:
寶馬
藍色
奧迪
白色
保時捷
黃色
寫完XML文件,布局文件不寫,直接寫代碼,解析xml文件。
.
(二)三種讀取xml文件的方法的代碼
package com.example.resource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
public class MainActivity extends Activity {
// 要解析文件的輸入流
InputStream is;
// 創建一個List集合存放從XML文件獲取到的數據
List list = null;
Car car = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pullXml();// 使用pull解析
saxXml();// 使用Sax解析
domXml();// 使用DOM解析
}
----------//開始解析數據
// 使用DOM解析數據
private void domXml() {
list = new ArrayList();
try {
// 從assets裡面獲取文件,
// 通過getAssets獲取到的是讀取流
is = getAssets().open("cars.xml");
// 取得DocumentBuilderFactory實例
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
// 從factory獲取DocumentBuilder實例
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析輸入流 得到Document實例
org.w3c.dom.Document doc = builder.parse(is);
Element root = doc.getDocumentElement();
NodeList items = root.getElementsByTagName("Car");
for (int i = 0; i < items.getLength(); i++) {
car = new Car();
Element item = (Element) items.item(i);
// 獲取id屬性
car.id = item.getAttribute("id");
NodeList properties = item.getChildNodes();
for (int j = 0; j < properties.getLength(); j++) {
Node property = properties.item(j);
String nodeName = property.getNodeName();
// 獲取節點值的具體代碼
if (nodeName.equals("mark")) {
car.mark = property.getFirstChild().getNodeValue();
} else if (nodeName.equals("color")) {
car.color = property.getFirstChild().getNodeValue();
}
}
list.add(car);
}
for (Car c : list) {
Log.e("DOM", c.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
----------
//上面是DOM解析數據的過程
----------
// 使用SAX方法解析的結果
private void saxXml() {
try {
// 從assets裡面獲取文件,
// 通過getAssets獲取到的是讀取流
is = getAssets().open("cars.xml");
// 取得SAXParserFactory實例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 從factory獲取SAXParser實例
SAXParser parser = factory.newSAXParser();
// 實例化定義的Handler
Myhandler handler = new Myhandler();
// 根據Handler規則解析輸入流
parser.parse(is, handler);
// 打印信息
handler.showMessage();
} catch (Exception e) {
e.printStackTrace();
}
// 實例話
}
//實現SAX方法解析數據必須要借助DefaultHandler 類的實現
class Myhandler extends DefaultHandler {
StringBuffer sb = null;
// 根標簽開始時
@Override
public void startDocument() throws SAXException {
super.startDocument();
list = new ArrayList();
sb = new StringBuffer();
}
// 節點開始時
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// 當遍歷到Car節點就新建Car對象
if (localName.equals("Car")) {
car = new Car();
car.id = attributes.getValue(0);// 獲取第一個屬性值,節點值在後面獲取
}
// 將字符長度設置為零,以便從新開始讀取元素內就字符節點
sb.setLength(0);
}
// 讀取字符流
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
sb.append(ch, start, length);
}
// 節點結束時
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if (localName.equals("mark")) {
car.mark = sb.toString();
} else if (localName.equals("color")) {
car.color = sb.toString();
} else if (localName.equals("Car")) {
list.add(car);
}
}
public void showMessage() {
// 打印獲得的數據
for (Car c : list) {
Log.e("SAX", c.toString());
}
}
}
----------
//上面是SAX方法解析數據的過程
----------
// 使用pull方法解析文件的具體操作
private void pullXml() {
try {
// 從assets裡面獲取文件,
// 通過getAssets獲取到的是讀取流
is = getAssets().open("cars.xml");
// 創建一個pull解析對象,並獲取示例
XmlPullParser pull = Xml.newPullParser();
// 設置解析格式
pull.setInput(is, "utf-8");
// 開始解析
// 產生事件用來循環
int type = pull.getEventType();
// 實例化List集合存放從XML文件獲取到的數據
list = new ArrayList();
// 通過判斷事件,來獲取相應的數據
while (type != XmlPullParser.END_DOCUMENT) {// 沒到結束的根標簽就一直循環獲取
// 通過判斷事件,
switch (type) {
case XmlPullParser.START_TAG:// 標簽開始
// 獲取節點值節點屬性值的具體代碼
if (pull.getName().equals("Car")) {// 當遍歷到標簽開始是Car
// 新建Car對象
car = new Car();
// 獲取標簽屬性id,屬性值和節點值的取法是不一樣的
car.id = pull.getAttributeValue(0);
} else if (pull.getName().equals("mark")) {
// 獲取標簽的信息
car.mark = pull.nextText();
} else if (pull.getName().equals("color")) {
car.color = pull.nextText();
}
break;
case XmlPullParser.END_TAG:// 標簽結束時
// 如果是Car標簽結束,就對數據對象進行存儲
if (pull.getName().equals("Car")) {
list.add(car);
}
break;
default:
break;
}
// 繼續下一個標簽
pull.next();
type = pull.getEventType();
}
// 打印一下集合的數據
for (Car car2 : list) {
Log.e("pull", car2.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
----------
//上面的使用pull方法解析文件的過程
----------
//定義一個對象類,用來存放和顯示數據
static class Car {
String id;
String color;
String mark;
@Override
public String toString() {
return "Car [id=" + id + ", color=" + color + ", mark=" + mark
+ "]";
}
}
}
程序運行後顯示的Log內容如下:
???上面就是三種解析XML數據的方法,其中值得注意的是截取節點的值和截取節點的屬性的值用的方法是不一樣的。也要區分根節點和普通節點要執行的相關操作。
???本示例主要數實現數據的解析過程,相關數據的處理沒有很好的表現出來,但是結果都是能解析出正確的數值的。
???對於這三種解析器各有優點,一般推薦使用PULL解析器,因為SAX解析器操作起來太笨重,DOM不適合文檔較大,內存較小的場景,唯有PULL輕巧靈活,速度快,占用內存小, 使用非常順手。大家也可以根據自己的喜好選擇相應的解析技術。
???上面是解析xml文件的三種基本方式,後面也會接觸到很多其他封裝類的解析方法。但是都是在上面基礎上設計的。
話說為了防止偷拍,業內有不成文規定,手機公司在做camera時,點擊拍照和錄像鍵的時候,必須要有提示音。因此,google也就非常人性化的將播放拍照聲音的函數,放到了ca
一、前言 本篇blog是我的“Android進階”的第一篇文章,從初學Android到現在斷斷續續也有4個多月時間了,也算是有了一些自己的心得體會,也能自
本文采用一個Demo來展示Android中ExpandableListView控件的使用,如如何在組/子ListView中綁定數據源。直接上代碼如下:程序結構圖:layo
0x1 開始Anddroid上的ART從5.0之後變成默認的選擇,可見ART的重要性,目前關於Dalvik Hook方面研究的文章很多,但我在網上