Android中XML数据解析
转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38296207
XML初步
Android中XML数据解析使用实例
- <?xml version=“1.0” encoding=“UTF-8”?>
- <persons>
- <person id=“1”>
- <name>Transformers First</name>
- <height>7</height>
- <imageurl>imagefile/transformers_one.png</imageurl>
- </person>
- <person id=“2”>
- <name>Transformers second</name>
- <height>4</height>
- <imageurl>imagefile/transformers_two.png</imageurl>
- </person>
- <person id=“3”>
- <name>Transformers third</name>
- <height>8.5</height>
- <imageurl>imagefile/transformers_three.png</imageurl>
- </person>
- <person id=“4”>
- <name>Transformers fourth</name>
- <height>14.5</height>
- <imageurl>imagefile/transformers_four.png</imageurl>
- </person>
- <person id=“5”>
- <name>Transformers fifth</name>
- <height>27.5</height>
- <imageurl>imagefile/transformers_five.png</imageurl>
- </person>
- <person id=“6”>
- <name>Transformers Sixth</name>
- <height>8.5</height>
- <imageurl>imagefile/transformers_six.png</imageurl>
- </person>
- <person id=“7”>
- <name>Transformers Seventh</name>
- <height>5</height>
- <imageurl>imagefile/transformers_seven.png</imageurl>
- </person>
- <person id=“8”>
- <name>Transformers Eighth</name>
- <height>12.5</height>
- <imageurl>imagefile/transformers_eight.png</imageurl>
- </person>
- </persons>
<?xml version="1.0" encoding="UTF-8"?>
<persons><person id="1"><name>Transformers First</name><height>7</height><imageurl>imagefile/transformers_one.png</imageurl></person><person id="2"><name>Transformers second</name><height>4</height><imageurl>imagefile/transformers_two.png</imageurl></person><person id="3"><name>Transformers third</name><height>8.5</height><imageurl>imagefile/transformers_three.png</imageurl></person><person id="4"><name>Transformers fourth</name><height>14.5</height><imageurl>imagefile/transformers_four.png</imageurl></person><person id="5"><name>Transformers fifth</name><height>27.5</height><imageurl>imagefile/transformers_five.png</imageurl></person><person id="6"><name>Transformers Sixth</name><height>8.5</height><imageurl>imagefile/transformers_six.png</imageurl></person><person id="7"><name>Transformers Seventh</name><height>5</height><imageurl>imagefile/transformers_seven.png</imageurl></person><person id="8"><name>Transformers Eighth</name><height>12.5</height><imageurl>imagefile/transformers_eight.png</imageurl></person>
</persons>
SAX解析XML文件实例
- /**
- * SAX解析类
- * @author AndroidLeaf
- */
- public class MyHandler extends DefaultHandler {
- //当开始读取文档标签时调用该方法
- @Override
- public void startDocument() throws SAXException {
- // TODO Auto-generated method stub
- super.startDocument();
- }
- //当开始读取节点元素标签时调用该方法
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- // TODO Auto-generated method stub
- super.startElement(uri, localName, qName, attributes);
- //do something
- }
- //当读取节点元素的子类信息时调用该方法
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- // TODO Auto-generated method stub
- super.characters(ch, start, length);
- //do something
- }
- //当结束读取节点元素标签时调用该方法
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- // TODO Auto-generated method stub
- super.endElement(uri, localName, qName);
- //do something
- }
- //当结束读取文档标签时调用该方法
- @Override
- public void endDocument() throws SAXException {
- // TODO Auto-generated method stub
- super.endDocument();
- //do something
- }
- }
/*** SAX解析类* @author AndroidLeaf*/
public class MyHandler extends DefaultHandler {//当开始读取文档标签时调用该方法@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();}//当开始读取节点元素标签时调用该方法@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stubsuper.startElement(uri, localName, qName, attributes);//do something}//当读取节点元素的子类信息时调用该方法@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stubsuper.characters(ch, start, length);//do something}//当结束读取节点元素标签时调用该方法@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stubsuper.endElement(uri, localName, qName);//do something}//当结束读取文档标签时调用该方法@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();//do something}}
事件处理器名称 |
事件处理器处理的事件 |
ContentHandler |
XML文档的开始与结束; XML文档节点元素的开始与结束,接收字符数据,跳过实体,接收元素内容中可忽略的空白等。 |
DTDHandler |
处理DTD解析时产生的相应事件 |
ErrorHandler |
处理XML文档时产生的错误 |
EntityResolver |
处理外部实体 |
方法名称 |
方法说明 |
startDocument() |
用于处理文档解析开始时间 |
startElement(String uri,String localName,String qName Attributes attributes) |
处理元素开始时间,从参数中可以获取元素所在空间的URL,元素名称,属性列表等信息。 |
characters(char[] ch,int start,int length) |
处理元素的字符内容,从参数中可以获得内容 |
endElement(String uri,String localName,String qName) |
处理元素结束时间,从参数中可以获取元素所在空间的URL,元素名称等信息。 |
endDocument() |
用于处理文档解析的结束事件 |
- /**————–SAX解析XML——————-*/
- /**
- * @param mInputStream 需要解析的person.xml的文件流对象
- * @param nodeName 节点名称
- * @return mList Person对象集合
- */
- public static ArrayList<Person> saxAnalysis(InputStream mInputStream,String nodeName){
- //1、获取创建一个SAX解析工厂实例
- SAXParserFactory mSaxParserFactory = SAXParserFactory.newInstance();
- try {
- //2、调用工厂实例中的newSAXParser()方法创建SAXParser解析对象
- SAXParser mSaxParser = mSaxParserFactory.newSAXParser();
- //3、实例化CustomHandler(DefaultHandler的子类)
- CustomHandler mHandler = new CustomHandler(nodeName);
- /**
- * 4、连接事件源对象XMLReader到事件处理类DefaultHandler中
- * 查看parse(InputStream is, DefaultHandler dh)方法源码如下:
- * public void parse(InputSource is, DefaultHandler dh)
- * throws SAXException, IOException {
- * if (is == null) {
- * throw new IllegalArgumentException(“InputSource cannot be null”);
- * }
- * // 获取事件源XMLReader,并通过相应事件处理器注册方法setXXXX()来完成的与ContentHander、DTDHander、ErrorHandler,
- * // 以及EntityResolver这4个接口的连接。
- * XMLReader reader = this.getXMLReader();
- * if (dh != null) {
- * reader.setContentHandler(dh);
- * reader.setEntityResolver(dh);
- * reader.setErrorHandler(dh);
- * reader.setDTDHandler(dh);
- * }
- * reader.parse(is);
- * }
- */
- mSaxParser.parse(mInputStream, mHandler);
- //5、通过DefaultHandler返回我们需要的数据集合
- return mHandler.getList();
- } catch (ParserConfigurationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SAXException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
/**--------------SAX解析XML-------------------*//*** @param mInputStream 需要解析的person.xml的文件流对象* @param nodeName 节点名称* @return mList Person对象集合*/public static ArrayList<Person> saxAnalysis(InputStream mInputStream,String nodeName){//1、获取创建一个SAX解析工厂实例SAXParserFactory mSaxParserFactory = SAXParserFactory.newInstance();try {//2、调用工厂实例中的newSAXParser()方法创建SAXParser解析对象SAXParser mSaxParser = mSaxParserFactory.newSAXParser();//3、实例化CustomHandler(DefaultHandler的子类)CustomHandler mHandler = new CustomHandler(nodeName);/*** 4、连接事件源对象XMLReader到事件处理类DefaultHandler中* 查看parse(InputStream is, DefaultHandler dh)方法源码如下:* public void parse(InputSource is, DefaultHandler dh)* throws SAXException, IOException {* if (is == null) {* throw new IllegalArgumentException("InputSource cannot be null");* }* // 获取事件源XMLReader,并通过相应事件处理器注册方法setXXXX()来完成的与ContentHander、DTDHander、ErrorHandler,* // 以及EntityResolver这4个接口的连接。* XMLReader reader = this.getXMLReader();* if (dh != null) {* reader.setContentHandler(dh);* reader.setEntityResolver(dh);* reader.setErrorHandler(dh);* reader.setDTDHandler(dh);* }* reader.parse(is);* }*/mSaxParser.parse(mInputStream, mHandler);//5、通过DefaultHandler返回我们需要的数据集合return mHandler.getList();} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}
事件处理器类CustomerHandler中的具体代码如下:
- /**
- * SAX解析类
- * @author AndroidLeaf
- */
- public class CustomHandler extends DefaultHandler {
- //装载所有解析完成的内容
- List<HashMap<String, String>> mListMaps = null;
- //装载解析单个person节点的内容
- HashMap<String, String> map = null;
- //节点名称
- private String nodeName;
- //当前解析的节点标记
- private String currentTag;
- //当前解析的节点值
- private String currentValue;
- public ArrayList<Person> getList(){
- ArrayList<Person> mList = new ArrayList<Person>();
- if(mListMaps != null && mListMaps.size() > 0){
- for(int i = 0;i < mListMaps.size();i++){
- Person mPerson = new Person();
- HashMap<String, String> mHashMap = mListMaps.get(i);
- mPerson.setId(Integer.parseInt(mHashMap.get(”id”)));
- mPerson.setUserName(mHashMap.get(”name”));
- mPerson.setHeight(Float.parseFloat(mHashMap.get(”height”)));
- mPerson.setImageUrl(mHashMap.get(”imageurl”));
- mList.add(mPerson);
- }
- }
- return mList;
- }
- public CustomHandler(String nodeName){
- this.nodeName = nodeName;
- }
- @Override
- public void startDocument() throws SAXException {
- // TODO Auto-generated method stub
- super.startDocument();
- mListMaps = new ArrayList<HashMap<String, String>>();
- }
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- // TODO Auto-generated method stub
- if (qName.equals(nodeName)) {
- map = new HashMap<String, String>();
- }
- if (map != null && attributes != null) {
- for (int i = 0; i < attributes.getLength(); i++) {
- map.put(attributes.getQName(i), attributes.getValue(i));
- }
- }
- // 当前的解析的节点名称
- currentTag = qName;
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- // TODO Auto-generated method stub
- if (map != null && currentTag != null) {
- currentValue = new String(ch, start, length);
- if (currentValue != null && !currentValue.equals(“”)
- && !currentValue.equals(”\n”)) {
- map.put(currentTag, currentValue);
- }
- }
- currentTag = null;
- currentValue = null;
- super.characters(ch, start, length);
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- // TODO Auto-generated method stub
- if (qName.equals(nodeName)) {
- mListMaps.add(map);
- map = null;
- }
- super.endElement(uri, localName, qName);
- }
- @Override
- public void endDocument() throws SAXException {
- // TODO Auto-generated method stub
- super.endDocument();
- }
- }
/*** SAX解析类* @author AndroidLeaf*/
public class CustomHandler extends DefaultHandler {//装载所有解析完成的内容List<HashMap<String, String>> mListMaps = null;//装载解析单个person节点的内容HashMap<String, String> map = null;//节点名称private String nodeName;//当前解析的节点标记private String currentTag;//当前解析的节点值private String currentValue;public ArrayList<Person> getList(){ArrayList<Person> mList = new ArrayList<Person>();if(mListMaps != null && mListMaps.size() > 0){for(int i = 0;i < mListMaps.size();i++){Person mPerson = new Person();HashMap<String, String> mHashMap = mListMaps.get(i);mPerson.setId(Integer.parseInt(mHashMap.get("id")));mPerson.setUserName(mHashMap.get("name"));mPerson.setHeight(Float.parseFloat(mHashMap.get("height")));mPerson.setImageUrl(mHashMap.get("imageurl"));mList.add(mPerson);}}return mList;}public CustomHandler(String nodeName){this.nodeName = nodeName;}@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();mListMaps = new ArrayList<HashMap<String, String>>();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stubif (qName.equals(nodeName)) {map = new HashMap<String, String>();}if (map != null && attributes != null) {for (int i = 0; i < attributes.getLength(); i++) {map.put(attributes.getQName(i), attributes.getValue(i));}}// 当前的解析的节点名称currentTag = qName;}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stubif (map != null && currentTag != null) {currentValue = new String(ch, start, length);if (currentValue != null && !currentValue.equals("")&& !currentValue.equals("\n")) {map.put(currentTag, currentValue);}}currentTag = null;currentValue = null;super.characters(ch, start, length);}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stubif (qName.equals(nodeName)) {mListMaps.add(map);map = null;}super.endElement(uri, localName, qName);}@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();}
}
CustomerHandler通过不断接收事件源传递过来的事件,进而执行相关解析工作并调用对应的方法,然后以参数的形式接收解析结果。为了更好的让读者理解CustomerHandler的解析过程,下面有一张展示解析person.xml文件的流程图,如下:
DOM解析XML文件实例
DOM的工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档——这就是DOM的工作原理。DOM实现时首先为XML文档的解析定义一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,这样代码就可以使用DOM接口来操作整个树结构。由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。 当然,如果XML文件的内容比较小,采用DOM是可行的。下面罗列了一些使用DOM解析时常用的接口和类,如下:
接口或类名称 |
接口或类说明 |
Document |
该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础。 |
Element |
该接口继承Node接口,提供了获取、修改XML元素名字和属性的方法 |
Node |
该接口提供处理并获取节点和子节点值的方法 |
NodeList |
提供获得子节点个数和当前节点的方法。这样就可以迭代地访问各个节点 |
DOMParser |
该类是Apache的Xerces中的DOM解析器类,可直接解析XML。 |
接下来我们学习一下使用DOM解析XML的编程步骤,一般分为6个步骤,如下:
然后,我们按照这6个步骤来完成Demo实例解析person.xml的工作(person.xml的内容上面已经列出),解析的关键代码是在Demo实例工程中的XmlTools类中,具体代码如下:
- /**————–DOM解析XML——————-*/
- /**
- * @param mInputStream 需要解析的person.xml的文件流对象
- * @return mList Person对象集合
- */
- public static ArrayList<Person> domAnalysis(InputStream mInputStream){
- ArrayList<Person> mList = new ArrayList<Person>();
- //1、创建文档对象工厂实例
- DocumentBuilderFactory mDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
- try {
- //2、调用DocumentBuilderFactory中的newDocumentBuilder()方法创建文档对象构造器
- DocumentBuilder mDocumentBuilder = mDocumentBuilderFactory.newDocumentBuilder();
- //3、将文件流解析成XML文档对象
- Document mDocument = mDocumentBuilder.parse(mInputStream);
- //4、使用mDocument文档对象得到文档根节点
- Element mElement = mDocument.getDocumentElement();
- //5、根据名称获取根节点中的子节点列表
- NodeList mNodeList = mElement.getElementsByTagName(”person”);
- //6 、获取子节点列表中需要读取的节点信息
- for(int i = 0 ;i < mNodeList.getLength();i++){
- Person mPerson = new Person();
- Element personElement = (Element) mNodeList.item(i);
- //获取person节点中的属性
- if(personElement.hasAttributes()){
- mPerson.setId(Integer.parseInt(personElement.getAttribute(”id”)));
- }
- if(personElement.hasChildNodes()){
- //获取person节点的子节点列表
- NodeList mNodeList2 = personElement.getChildNodes();
- //遍历子节点列表并赋值
- for(int j = 0;j < mNodeList2.getLength();j++){
- Node mNodeChild = mNodeList2.item(j);
- if(mNodeChild.getNodeType() == Node.ELEMENT_NODE){
- if(“name”.equals(mNodeChild.getNodeName())){
- mPerson.setUserName(mNodeChild.getFirstChild().getNodeValue());
- }else if(“height”.equals(mNodeChild.getNodeName())){
- mPerson.setHeight(Float.parseFloat(mNodeChild.getFirstChild().getNodeValue()));
- }else if(“imageurl”.equals(mNodeChild.getNodeName())){
- mPerson.setImageUrl(mNodeChild.getFirstChild().getNodeValue());
- }
- }
- }
- }
- mList.add(mPerson);
- }
- } catch (ParserConfigurationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SAXException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return mList;
- }
/**--------------DOM解析XML-------------------*//*** @param mInputStream 需要解析的person.xml的文件流对象* @return mList Person对象集合*/public static ArrayList<Person> domAnalysis(InputStream mInputStream){ArrayList<Person> mList = new ArrayList<Person>();//1、创建文档对象工厂实例DocumentBuilderFactory mDocumentBuilderFactory = DocumentBuilderFactory.newInstance();try {//2、调用DocumentBuilderFactory中的newDocumentBuilder()方法创建文档对象构造器DocumentBuilder mDocumentBuilder = mDocumentBuilderFactory.newDocumentBuilder();//3、将文件流解析成XML文档对象Document mDocument = mDocumentBuilder.parse(mInputStream);//4、使用mDocument文档对象得到文档根节点Element mElement = mDocument.getDocumentElement();//5、根据名称获取根节点中的子节点列表NodeList mNodeList = mElement.getElementsByTagName("person");//6 、获取子节点列表中需要读取的节点信息for(int i = 0 ;i < mNodeList.getLength();i++){Person mPerson = new Person();Element personElement = (Element) mNodeList.item(i);//获取person节点中的属性if(personElement.hasAttributes()){mPerson.setId(Integer.parseInt(personElement.getAttribute("id")));}if(personElement.hasChildNodes()){//获取person节点的子节点列表NodeList mNodeList2 = personElement.getChildNodes();//遍历子节点列表并赋值for(int j = 0;j < mNodeList2.getLength();j++){Node mNodeChild = mNodeList2.item(j);if(mNodeChild.getNodeType() == Node.ELEMENT_NODE){if("name".equals(mNodeChild.getNodeName())){mPerson.setUserName(mNodeChild.getFirstChild().getNodeValue());}else if("height".equals(mNodeChild.getNodeName())){mPerson.setHeight(Float.parseFloat(mNodeChild.getFirstChild().getNodeValue()));}else if("imageurl".equals(mNodeChild.getNodeName())){mPerson.setImageUrl(mNodeChild.getFirstChild().getNodeValue());}}}}mList.add(mPerson);}} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return mList;}
PULL解析XML文件实例
接口和类名称 |
接口和类说明 |
XmlPullParser |
XML Pull解析接口,该接口定义了解析功能 |
XmlSerializer |
它是一个接口,定义了XML信息集的序列 |
XmlPullParserFactory |
XML PULL解析工厂类,用于创建XML Pull解析器 |
XmlPullParserException |
抛出单一的XML pull解析器相关的错误 |
方法名 |
方法说明 |
getEventType() |
该方法用于获取当前解析到的事件类型 |
nextText() |
提取当前节点元素的字符数据 |
next() |
获取下一个节点元素的类型 |
getName() |
获取当前节点元素的名称 |
getAttributeCount() |
获取当前节点属性的数量 |
XmlPullParser.START_DOCUMENT |
文档开始解析类型 |
XmlPullParser.END_DOCUMENT |
文档结束解析类型 |
XmlPullParser.START_TAG |
节点开始解析类型 |
XmlPullParser.END_TAG |
节点结束解析类型 |
XmlPullParser.TEXT |
文本解析类型 |
- /**————–PULL解析XML——————-*/
- /**
- * @param mInputStream 需要解析的person.xml的文件流对象
- * @param encode 设置字符编码
- * @return mList Person对象集合
- */
- public static ArrayList<Person> PullAnalysis(InputStream mInputStream,String encode){
- ArrayList<Person> mList = null;
- Person mPerson = null;
- try {
- //1、获取PULL解析工厂实例对象
- XmlPullParserFactory mXmlPullParserFactory = XmlPullParserFactory.newInstance();
- //2、使用XmlPullParserFactory的newPullParser()方法实例化PULL解析实例对象
- XmlPullParser mXmlPullParser = mXmlPullParserFactory.newPullParser();
- //3、设置需解析的XML文件流和字符编码
- mXmlPullParser.setInput(mInputStream, encode);
- //4、获取事件解析类型
- int eventType = mXmlPullParser.getEventType();
- //5、循环遍历解析,当文档解析结束时结束循环
- while(eventType != XmlPullParser.END_DOCUMENT){
- switch (eventType) {
- //开始解析文档
- case XmlPullParser.START_DOCUMENT:
- mList = new ArrayList<Person>();
- break;
- //开始解析节点
- case XmlPullParser.START_TAG:
- if(“person”.equals(mXmlPullParser.getName())){
- mPerson = new Person();
- //获取该节点中的属性的数量
- int attributeNumber = mXmlPullParser.getAttributeCount();
- if(attributeNumber > 0){
- //获取属性值
- mPerson.setId(Integer.parseInt(mXmlPullParser.getAttributeValue(0)));
- }
- }else if(“name”.equals(mXmlPullParser.getName())){
- //获取该节点的内容
- mPerson.setUserName(mXmlPullParser.nextText());
- }else if(“height”.equals(mXmlPullParser.getName())){
- mPerson.setHeight(Float.parseFloat(mXmlPullParser.nextText()));
- }else if(“imageurl”.equals(mXmlPullParser.getName())){
- mPerson.setImageUrl(mXmlPullParser.nextText());
- }
- break;
- //解析节点结束
- case XmlPullParser.END_TAG:
- if(“person”.equals(mXmlPullParser.getName())){
- mList.add(mPerson);
- mPerson = null;
- }
- break;
- default:
- break;
- }
- eventType = mXmlPullParser.next();
- }
- } catch (XmlPullParserException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return mList;
- }
/**--------------PULL解析XML-------------------*//*** @param mInputStream 需要解析的person.xml的文件流对象* @param encode 设置字符编码* @return mList Person对象集合*/public static ArrayList<Person> PullAnalysis(InputStream mInputStream,String encode){ArrayList<Person> mList = null;Person mPerson = null;try {//1、获取PULL解析工厂实例对象XmlPullParserFactory mXmlPullParserFactory = XmlPullParserFactory.newInstance();//2、使用XmlPullParserFactory的newPullParser()方法实例化PULL解析实例对象XmlPullParser mXmlPullParser = mXmlPullParserFactory.newPullParser();//3、设置需解析的XML文件流和字符编码mXmlPullParser.setInput(mInputStream, encode);//4、获取事件解析类型int eventType = mXmlPullParser.getEventType();//5、循环遍历解析,当文档解析结束时结束循环while(eventType != XmlPullParser.END_DOCUMENT){switch (eventType) {//开始解析文档case XmlPullParser.START_DOCUMENT:mList = new ArrayList<Person>();break;//开始解析节点case XmlPullParser.START_TAG:if("person".equals(mXmlPullParser.getName())){mPerson = new Person();//获取该节点中的属性的数量int attributeNumber = mXmlPullParser.getAttributeCount();if(attributeNumber > 0){//获取属性值mPerson.setId(Integer.parseInt(mXmlPullParser.getAttributeValue(0)));}}else if("name".equals(mXmlPullParser.getName())){//获取该节点的内容mPerson.setUserName(mXmlPullParser.nextText());}else if("height".equals(mXmlPullParser.getName())){mPerson.setHeight(Float.parseFloat(mXmlPullParser.nextText()));}else if("imageurl".equals(mXmlPullParser.getName())){mPerson.setImageUrl(mXmlPullParser.nextText());}break;//解析节点结束case XmlPullParser.END_TAG:if("person".equals(mXmlPullParser.getName())){mList.add(mPerson);mPerson = null;}break;default:break;}eventType = mXmlPullParser.next();}} catch (XmlPullParserException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return mList;}
- /**
- * 网络访问类
- * @author AndroidLeaf
- */
- public class HttpRequest {
- /**
- * @param urlStr 请求的Url
- * @return InputStream 返回请求的流数据
- */
- public static InputStream getInputStreamFromNetWork(String urlStr)
- {
- URL mUrl = null;
- HttpURLConnection mConnection= null;
- InputStream mInputStream = null;
- try {
- mUrl = new URL(urlStr);
- mConnection = (HttpURLConnection)mUrl.openConnection();
- mConnection.setDoOutput(true);
- mConnection.setDoInput(true);
- mConnection.setReadTimeout(15 * 1000);
- mConnection.setConnectTimeout(15 * 1000);
- mConnection.setRequestMethod(”GET”);
- int responseCode = mConnection.getResponseCode();
- if(responseCode == HttpURLConnection.HTTP_OK){
- //获取下载资源的大小
- //contentLength = mConnection.getContentLength();
- mInputStream = mConnection.getInputStream();
- return mInputStream;
- }
- } catch (IOException e) {
- // TODO: handle exception
- }
- return null;
- }
- /**
- * 得到图片字节流 数组大小
- * */
- public static byte[] readStream(InputStream mInputStream){
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- byte[] buffer = new byte[2048];
- int len = 0;
- try {
- while((len = mInputStream.read(buffer)) != -1){
- outStream.write(buffer, 0, len);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }finally{
- try {
- if(outStream != null){
- outStream.close();
- }
- if(mInputStream != null){
- mInputStream.close();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return outStream.toByteArray();
- }
/*** 网络访问类* @author AndroidLeaf*/
public class HttpRequest {/*** @param urlStr 请求的Url* @return InputStream 返回请求的流数据*/public static InputStream getInputStreamFromNetWork(String urlStr){URL mUrl = null;HttpURLConnection mConnection= null;InputStream mInputStream = null;try {mUrl = new URL(urlStr);mConnection = (HttpURLConnection)mUrl.openConnection();mConnection.setDoOutput(true);mConnection.setDoInput(true);mConnection.setReadTimeout(15 * 1000);mConnection.setConnectTimeout(15 * 1000);mConnection.setRequestMethod("GET");int responseCode = mConnection.getResponseCode();if(responseCode == HttpURLConnection.HTTP_OK){//获取下载资源的大小//contentLength = mConnection.getContentLength();mInputStream = mConnection.getInputStream();return mInputStream;} } catch (IOException e) {// TODO: handle exception}return null;}/*** 得到图片字节流 数组大小* */public static byte[] readStream(InputStream mInputStream){ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; int len = 0; try {while((len = mInputStream.read(buffer)) != -1){ outStream.write(buffer, 0, len); }} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {if(outStream != null){outStream.close();}if(mInputStream != null){mInputStream.close();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} } return outStream.toByteArray(); }
接着实现MyAsynctask类的代码,如下:
- /**
- * 异步请求工具类
- * @author AndroidLeaf
- */
- public class MyAsynctask extends AsyncTask<Object, Void, Object> {
- private ImageView mImageView;
- private ImageCallBack mImageCallBack;
- //请求类型,分为XML文件请求和图片下载请求
- private int typeId;
- //使用的XML解析类型ID
- private int requestId;
- /**
- * 定义一个回调,用于监听网络请求,当请求结束,返回访问结果
- */
- public HttpDownloadedListener mHttpDownloadedListener;
- public interface HttpDownloadedListener{
- public void onDownloaded(String result,int requestId);
- }
- public void setOnHttpDownloadedListener(HttpDownloadedListener mHttpDownloadedListener){
- this.mHttpDownloadedListener = mHttpDownloadedListener;
- }
- public MyAsynctask(ImageView mImageView,ImageCallBack mImageCallBack,int requestId){
- this.mImageView = mImageView;
- this.mImageCallBack = mImageCallBack;
- this.requestId = requestId;
- }
- @Override
- protected void onPreExecute() {
- // TODO Auto-generated method stub
- super.onPreExecute();
- }
- @Override
- protected Object doInBackground(Object… params) {
- // TODO Auto-generated method stub
- InputStream mInputStream = HttpRequest.getInputStreamFromNetWork((String)params[0]);
- if(mInputStream != null){
- switch ((int)params[1]) {
- case Constants.TYPE_STR:
- typeId = Constants.TYPE_STR;
- return WriteIntoFile(mInputStream);
- case Constants.TYPE_STREAM:
- typeId = Constants.TYPE_STREAM;
- return getBitmap(HttpRequest.readStream(mInputStream),
- 200, 200);
- default:
- break;
- }
- }
- return null;
- }
- @Override
- protected void onPostExecute(Object result) {
- // TODO Auto-generated method stub
- if(result != null){
- switch (typeId) {
- case Constants.TYPE_STR:
- mHttpDownloadedListener.onDownloaded((String)result,requestId);
- break;
- case Constants.TYPE_STREAM:
- mImageCallBack.resultImage(mImageView,(Bitmap)result);
- break;
- default:
- break;
- }
- typeId = -1;
- }
- super.onPostExecute(result);
- }
- public Bitmap getBitmap(byte[] bytes,int width,int height){
- //获取屏幕的宽和高
- /**
- * 为了计算缩放的比例,我们需要获取整个图片的尺寸,而不是图片
- * BitmapFactory.Options类中有一个布尔型变量inJustDecodeBounds,将其设置为true
- * 这样,我们获取到的就是图片的尺寸,而不用加载图片了。
- * 当我们设置这个值的时候,我们接着就可以从BitmapFactory.Options的outWidth和outHeight中获取到值
- */
- BitmapFactory.Options op = new BitmapFactory.Options();
- op.inJustDecodeBounds = true;
- Bitmap pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
- int wRatio = (int) Math.ceil(op.outWidth / (float) width); //计算宽度比例
- int hRatio = (int) Math.ceil(op.outHeight / (float) height); //计算高度比例
- /**
- * 接下来,我们就需要判断是否需要缩放以及到底对宽还是高进行缩放。
- * 如果高和宽不是全都超出了屏幕,那么无需缩放。
- * 如果高和宽都超出了屏幕大小,则如何选择缩放呢》
- * 这需要判断wRatio和hRatio的大小
- * 大的一个将被缩放,因为缩放大的时,小的应该自动进行同比率缩放。
- * 缩放使用的还是inSampleSize变量
- */
- if (wRatio > 1 && hRatio > 1) {
- if (wRatio > hRatio) {
- op.inSampleSize = wRatio;
- } else {
- op.inSampleSize = hRatio;
- }
- }
- op.inJustDecodeBounds = false; //注意这里,一定要设置为false,因为上面我们将其设置为true来获取图片尺寸了
- pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
- return pic;
- }
- /**
- * 将下载的XML文件流存储到手机指定的SDcard目录下
- * @param mInputStream 需要读入的流
- * @return String 返回存储的XML文件的路径
- */
- public String WriteIntoFile(InputStream mInputStream){
- if(isSDcard()){
- try {
- FileOutputStream mOutputStream = new FileOutputStream(new File(getFileName()));
- int len = -1;
- byte[] bytes = new byte[2048];
- try {
- while((len = mInputStream.read(bytes)) != -1){
- mOutputStream.write(bytes, 0, len);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }finally{
- try {
- if(mOutputStream != null){
- mOutputStream.close();
- }
- if(mInputStream != null){
- mInputStream.close();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return getFileName();
- }
- return null;
- }
- /**
- * 检测SDcard是否可用
- * @return
- */
- public boolean isSDcard(){
- if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
- return true;
- }else{
- return false;
- }
- }
- /**
- * 获取需要存储的XML文件的路径
- * @return String 路径
- */
- public String getFileName(){
- String path = Environment.getExternalStorageDirectory().getPath() +”/XMLFiles”;
- File mFile = new File(path);
- if(!mFile.exists()){
- mFile.mkdirs();
- }
- return mFile.getPath() + “/xmlfile.xml”;
- }
/*** 异步请求工具类* @author AndroidLeaf*/
public class MyAsynctask extends AsyncTask<Object, Void, Object> {private ImageView mImageView;private ImageCallBack mImageCallBack;//请求类型,分为XML文件请求和图片下载请求private int typeId;//使用的XML解析类型IDprivate int requestId;/*** 定义一个回调,用于监听网络请求,当请求结束,返回访问结果*/public HttpDownloadedListener mHttpDownloadedListener;public interface HttpDownloadedListener{public void onDownloaded(String result,int requestId);}public void setOnHttpDownloadedListener(HttpDownloadedListener mHttpDownloadedListener){this.mHttpDownloadedListener = mHttpDownloadedListener;}public MyAsynctask(ImageView mImageView,ImageCallBack mImageCallBack,int requestId){this.mImageView = mImageView;this.mImageCallBack = mImageCallBack;this.requestId = requestId;}@Overrideprotected void onPreExecute() {// TODO Auto-generated method stubsuper.onPreExecute();}@Overrideprotected Object doInBackground(Object... params) {// TODO Auto-generated method stubInputStream mInputStream = HttpRequest.getInputStreamFromNetWork((String)params[0]);if(mInputStream != null){switch ((int)params[1]) {case Constants.TYPE_STR:typeId = Constants.TYPE_STR;return WriteIntoFile(mInputStream);case Constants.TYPE_STREAM:typeId = Constants.TYPE_STREAM;return getBitmap(HttpRequest.readStream(mInputStream),200, 200);default:break;}}return null;}@Overrideprotected void onPostExecute(Object result) {// TODO Auto-generated method stubif(result != null){switch (typeId) {case Constants.TYPE_STR:mHttpDownloadedListener.onDownloaded((String)result,requestId);break;case Constants.TYPE_STREAM:mImageCallBack.resultImage(mImageView,(Bitmap)result);break;default:break;}typeId = -1;}super.onPostExecute(result);}public Bitmap getBitmap(byte[] bytes,int width,int height){//获取屏幕的宽和高 /** * 为了计算缩放的比例,我们需要获取整个图片的尺寸,而不是图片 * BitmapFactory.Options类中有一个布尔型变量inJustDecodeBounds,将其设置为true * 这样,我们获取到的就是图片的尺寸,而不用加载图片了。 * 当我们设置这个值的时候,我们接着就可以从BitmapFactory.Options的outWidth和outHeight中获取到值 */ BitmapFactory.Options op = new BitmapFactory.Options(); op.inJustDecodeBounds = true; Bitmap pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);int wRatio = (int) Math.ceil(op.outWidth / (float) width); //计算宽度比例 int hRatio = (int) Math.ceil(op.outHeight / (float) height); //计算高度比例/** * 接下来,我们就需要判断是否需要缩放以及到底对宽还是高进行缩放。 * 如果高和宽不是全都超出了屏幕,那么无需缩放。 * 如果高和宽都超出了屏幕大小,则如何选择缩放呢》 * 这需要判断wRatio和hRatio的大小 * 大的一个将被缩放,因为缩放大的时,小的应该自动进行同比率缩放。 * 缩放使用的还是inSampleSize变量 */ if (wRatio > 1 && hRatio > 1) { if (wRatio > hRatio) { op.inSampleSize = wRatio; } else { op.inSampleSize = hRatio; } } op.inJustDecodeBounds = false; //注意这里,一定要设置为false,因为上面我们将其设置为true来获取图片尺寸了 pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);return pic;}/*** 将下载的XML文件流存储到手机指定的SDcard目录下* @param mInputStream 需要读入的流* @return String 返回存储的XML文件的路径*/public String WriteIntoFile(InputStream mInputStream){if(isSDcard()){try {FileOutputStream mOutputStream = new FileOutputStream(new File(getFileName()));int len = -1;byte[] bytes = new byte[2048];try {while((len = mInputStream.read(bytes)) != -1){mOutputStream.write(bytes, 0, len);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {if(mOutputStream != null){mOutputStream.close();}if(mInputStream != null){mInputStream.close();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}return getFileName();}return null;}/*** 检测SDcard是否可用* @return*/public boolean isSDcard(){if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){return true;}else{return false;}}/*** 获取需要存储的XML文件的路径* @return String 路径*/public String getFileName(){String path = Environment.getExternalStorageDirectory().getPath() +"/XMLFiles";File mFile = new File(path);if(!mFile.exists()){mFile.mkdirs();}return mFile.getPath() + "/xmlfile.xml";}
实现完网络请求的功能后,我们就可以从服务端获取到person.xml的文件流,然后再分别用SAX、DOM和PULL解析器将文件流解析(在上面介绍这几种解析器时已经实现了解析的代码,在工程中的XmlTools类中)成对应的Java对象集合,最后将Java对象集合以列表的形式展现在客户端界面上,那接下来我们将实现该功能。在工程中主要包含MainActivity、MyAdapter和ImageCallBack类,首先实现MainActivity的代码,如下:
- public class MainActivity extends ListActivity implements HttpDownloadedListener{
- private ProgressDialog mProgressDialog;
- //需要解析的节点名称
- private String nodeName = “person”;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_list);
- //初始化数据
- initData();
- }
- public void initData(){
- mProgressDialog = new ProgressDialog(this);
- mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- mProgressDialog.setTitle(”正在加载中…..”);
- mProgressDialog.show();
- //首次进入界面是,默认使用SAX解析数据
- downloadData(this,Constants.XML_PATH,Constants.REQUEST_PULL_TYPE,null,null,Constants.TYPE_STR);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // TOdO Auto-generated method stub
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // TOdO Auto-generated method stub
- int requestId = -1;
- switch (item.getItemId()) {
- case R.id.sax:
- requestId = Constants.REQUEST_SAX_TYPE;
- break;
- case R.id.dom:
- requestId = Constants.REQUEST_DOM_TYPE;
- break;
- case R.id.pull:
- requestId = Constants.REQUEST_PULL_TYPE;
- break;
- default:
- break;
- }
- downloadData(this, Constants.XML_PATH, requestId, null, null, Constants.TYPE_STR);
- mProgressDialog.show();
- return super.onOptionsItemSelected(item);
- }
- @Override
- public void onDownloaded(String result,int requestId) {
- // TODO Auto-generated method stub
- FileInputStream mFileInputStream = null;
- try {
- mFileInputStream = new FileInputStream(new File(result));
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- ArrayList<Person> mList = null;
- switch (requestId) {
- case Constants.REQUEST_SAX_TYPE:
- mList = XmlTools.saxAnalysis(mFileInputStream,nodeName);
- break;
- case Constants.REQUEST_DOM_TYPE:
- mList = XmlTools.domAnalysis(mFileInputStream);
- break;
- case Constants.REQUEST_PULL_TYPE:
- mList = XmlTools.PullAnalysis(mFileInputStream,”UTF-8”);
- break;
- default:
- break;
- }
- MyAdapter myAdapter = new MyAdapter(this, mList);
- setListAdapter(myAdapter);
- if(mProgressDialog.isShowing()){
- mProgressDialog.dismiss();
- }
- }
- //执行网络下载代码
- public static void downloadData(HttpDownloadedListener mDownloadedListener,String url,int requestId,ImageView mImageView,ImageCallBack mImageCallBack,int typeId){
- MyAsynctask mAsynctask = new MyAsynctask(mImageView,mImageCallBack,requestId);
- mAsynctask.setOnHttpDownloadedListener(mDownloadedListener);
- mAsynctask.execute(url,typeId);
- }
- }
public class MainActivity extends ListActivity implements HttpDownloadedListener{private ProgressDialog mProgressDialog;//需要解析的节点名称private String nodeName = "person";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);//初始化数据initData();}public void initData(){mProgressDialog = new ProgressDialog(this);mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);mProgressDialog.setTitle("正在加载中.....");mProgressDialog.show();//首次进入界面是,默认使用SAX解析数据downloadData(this,Constants.XML_PATH,Constants.REQUEST_PULL_TYPE,null,null,Constants.TYPE_STR);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// TOdO Auto-generated method stubgetMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// TOdO Auto-generated method stubint requestId = -1;switch (item.getItemId()) {case R.id.sax:requestId = Constants.REQUEST_SAX_TYPE;break;case R.id.dom:requestId = Constants.REQUEST_DOM_TYPE;break;case R.id.pull:requestId = Constants.REQUEST_PULL_TYPE;break;default:break;}downloadData(this, Constants.XML_PATH, requestId, null, null, Constants.TYPE_STR);mProgressDialog.show();return super.onOptionsItemSelected(item);}@Overridepublic void onDownloaded(String result,int requestId) {// TODO Auto-generated method stubFileInputStream mFileInputStream = null;try {mFileInputStream = new FileInputStream(new File(result));} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}ArrayList<Person> mList = null;switch (requestId) {case Constants.REQUEST_SAX_TYPE:mList = XmlTools.saxAnalysis(mFileInputStream,nodeName);break;case Constants.REQUEST_DOM_TYPE:mList = XmlTools.domAnalysis(mFileInputStream);break;case Constants.REQUEST_PULL_TYPE:mList = XmlTools.PullAnalysis(mFileInputStream,"UTF-8");break;default:break;}MyAdapter myAdapter = new MyAdapter(this, mList);setListAdapter(myAdapter);if(mProgressDialog.isShowing()){mProgressDialog.dismiss();}}//执行网络下载代码public static void downloadData(HttpDownloadedListener mDownloadedListener,String url,int requestId,ImageView mImageView,ImageCallBack mImageCallBack,int typeId){MyAsynctask mAsynctask = new MyAsynctask(mImageView,mImageCallBack,requestId);mAsynctask.setOnHttpDownloadedListener(mDownloadedListener);mAsynctask.execute(url,typeId);}}
然后再实现界面的适配器类–MyAdapter,具体代码如下:
- /**
- * 数据界面展示的适配器类
- * @author AndroidLeaf
- */
- public class MyAdapter extends BaseAdapter {
- private Context mContext;
- private ArrayList<Person> mList;
- private Bitmap[] mBitmaps;
- public MyAdapter(Context mContext,ArrayList<Person> mList){
- this.mContext = mContext;
- this.mList = mList;
- mBitmaps = new Bitmap[mList.size()];
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return mList.size();
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return mList.get(position);
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // TODO Auto-generated method stub
- ViewHolder mHolder;
- Person mPerson = mList.get(position);
- if(convertView == null){
- convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, null);
- mHolder = new ViewHolder();
- mHolder.mTextView_id = (TextView)convertView.findViewById(R.id.item_id);
- mHolder.mTextView_name = (TextView)convertView.findViewById(R.id.item_name);
- mHolder.mTextView_height = (TextView)convertView.findViewById(R.id.item_height);
- mHolder.mImageView_image = (ImageView)convertView.findViewById(R.id.item_image);
- //为Imageview设置TAG,作为每一个ImageView的唯一标识
- mHolder.mImageView_image.setTag(mPerson.getImageUrl());
- convertView.setTag(mHolder);
- }else{
- mHolder = (ViewHolder)convertView.getTag();
- }
- mHolder.mTextView_id.setText(String.valueOf(mPerson.getId()));
- mHolder.mTextView_name.setText(mPerson.getUserName());
- mHolder.mTextView_height.setText(String.valueOf(mPerson.getHeight()));
- /**
- * 解决异步加载过程中Listview列表中图片显示错位问题
- */
- //判断当前位置的ImageView和是否为上次执行加载操作的ImageView,若false则重置上次加载的那个Imageview中的图片资源
- if(!mPerson.getImageUrl().equals(String.valueOf(mHolder.mImageView_image.getTag()))){
- mHolder.mImageView_image.setImageResource(R.drawable.ic_launcher);
- }
- //重新为ImageView实例设置TAG
- mHolder.mImageView_image.setTag(mPerson.getImageUrl());
- if(mBitmaps[position] == null){
- //执行异步加载图片操作
- MainActivity.downloadData((HttpDownloadedListener)mContext, Constants.BASE_PATH + mPerson.getImageUrl(), -1,
- mHolder.mImageView_image, new MyImageCallBack(position,mPerson.getImageUrl()), Constants.TYPE_STREAM);
- }else{
- mHolder.mImageView_image.setImageBitmap(mBitmaps[position]);
- }
- return convertView;
- }
- class ViewHolder{
- TextView mTextView_id;
- TextView mTextView_name;
- TextView mTextView_height;
- ImageView mImageView_image;
- }
- class MyImageCallBack implements ImageCallBack{
- int index = -1;
- String imageUrl = null;
- public MyImageCallBack(int index,String imageUrl){
- this.index = index;
- this.imageUrl = imageUrl;
- }
- @Override
- public void resultImage(ImageView mImageView, Bitmap mBitmap) {
- // TODO Auto-generated method stub
- //判断当前显示的ImageView的URL是否与需要下载的图片ImageView的URL相同
- if(imageUrl.equals(String.valueOf(mImageView.getTag()))){
- mBitmaps[index] = mBitmap;
- mImageView.setImageBitmap(mBitmap);
- }
- }
- }
- }
/*** 数据界面展示的适配器类* @author AndroidLeaf*/
public class MyAdapter extends BaseAdapter {private Context mContext;private ArrayList<Person> mList;private Bitmap[] mBitmaps;public MyAdapter(Context mContext,ArrayList<Person> mList){this.mContext = mContext;this.mList = mList;mBitmaps = new Bitmap[mList.size()];}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mList.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn mList.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder mHolder;Person mPerson = mList.get(position);if(convertView == null){convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, null);mHolder = new ViewHolder();mHolder.mTextView_id = (TextView)convertView.findViewById(R.id.item_id);mHolder.mTextView_name = (TextView)convertView.findViewById(R.id.item_name);mHolder.mTextView_height = (TextView)convertView.findViewById(R.id.item_height);mHolder.mImageView_image = (ImageView)convertView.findViewById(R.id.item_image);//为Imageview设置TAG,作为每一个ImageView的唯一标识mHolder.mImageView_image.setTag(mPerson.getImageUrl());convertView.setTag(mHolder);}else{mHolder = (ViewHolder)convertView.getTag();}mHolder.mTextView_id.setText(String.valueOf(mPerson.getId()));mHolder.mTextView_name.setText(mPerson.getUserName());mHolder.mTextView_height.setText(String.valueOf(mPerson.getHeight()));/*** 解决异步加载过程中Listview列表中图片显示错位问题*///判断当前位置的ImageView和是否为上次执行加载操作的ImageView,若false则重置上次加载的那个Imageview中的图片资源if(!mPerson.getImageUrl().equals(String.valueOf(mHolder.mImageView_image.getTag()))){mHolder.mImageView_image.setImageResource(R.drawable.ic_launcher);}//重新为ImageView实例设置TAGmHolder.mImageView_image.setTag(mPerson.getImageUrl());if(mBitmaps[position] == null){//执行异步加载图片操作MainActivity.downloadData((HttpDownloadedListener)mContext, Constants.BASE_PATH + mPerson.getImageUrl(), -1, mHolder.mImageView_image, new MyImageCallBack(position,mPerson.getImageUrl()), Constants.TYPE_STREAM);}else{mHolder.mImageView_image.setImageBitmap(mBitmaps[position]);}return convertView;}class ViewHolder{TextView mTextView_id;TextView mTextView_name;TextView mTextView_height;ImageView mImageView_image;}class MyImageCallBack implements ImageCallBack{int index = -1;String imageUrl = null;public MyImageCallBack(int index,String imageUrl){this.index = index;this.imageUrl = imageUrl;}@Overridepublic void resultImage(ImageView mImageView, Bitmap mBitmap) {// TODO Auto-generated method stub//判断当前显示的ImageView的URL是否与需要下载的图片ImageView的URL相同if(imageUrl.equals(String.valueOf(mImageView.getTag()))){mBitmaps[index] = mBitmap;mImageView.setImageBitmap(mBitmap);}}}
}
观察上面的代码,在实现适配器类时,由于我们需要异步下载图片,因此在图片绑定和显示时由于列表项焦点的不断变换和图片数据加载的延迟会导致ListView中的图片显示错位的问题,为了解决该问题,我们采取对ImageView设置TAG来解决了图片错位问题,那要明白其中的原理,就必须对Listview加载item view列表项的实现机制比较清楚,由于该问题不是本文的重点,因此在此不便细讲,有兴趣的读者可以学习本博客的另一篇文章《Android异步加载数据时ListView中图片错位问题解析》,希望对你有所帮助。在实现图片异步加载时,程序中还使用到了一个非常有用的接口–ImageCallBack,该接口主要作用是将异步下载的图片设置到对应的Imageview控件中,该接口的具体代码如下:
- public interface ImageCallBack {
- public void resultImage(ImageView mImageView,Bitmap mBitmap);
- }
public interface ImageCallBack {public void resultImage(ImageView mImageView,Bitmap mBitmap);
}
当然,还有常量Constants类和Entity对象Person类。Constants类的具体的代码:
- /**
- * 网络请求的Url地址及一些常量
- * @author AndroidLeaf
- */
- public class Constants {
- //基路径
- public static final String BASE_PATH = “http://10.0.2.2:8080/09_Android_XMLServer_Blog/”;
- //person.xml网络请求路径
- public static final String XML_PATH = BASE_PATH + “xmlfile/person.xml”;
- //使用SAX解析的标签类型
- public static final int REQUEST_SAX_TYPE = 0;
- //使用DOM解析的标签类型
- public static final int REQUEST_DOM_TYPE = 1;
- //使用PULL解析的标签类型
- public static final int REQUEST_PULL_TYPE = 2;
- //请求person.xml文件标签
- public static final int TYPE_STR = 1;
- //请求图片文件标签
- public static final int TYPE_STREAM = 2;
- }
/*** 网络请求的Url地址及一些常量* @author AndroidLeaf*/
public class Constants {//基路径public static final String BASE_PATH = "http://10.0.2.2:8080/09_Android_XMLServer_Blog/";//person.xml网络请求路径public static final String XML_PATH = BASE_PATH + "xmlfile/person.xml";//使用SAX解析的标签类型public static final int REQUEST_SAX_TYPE = 0;//使用DOM解析的标签类型public static final int REQUEST_DOM_TYPE = 1;//使用PULL解析的标签类型public static final int REQUEST_PULL_TYPE = 2;//请求person.xml文件标签public static final int TYPE_STR = 1;//请求图片文件标签public static final int TYPE_STREAM = 2;}
Person类的代码如下:
- public class Person {
- private int id;
- private String userName;
- private float height;
- private String imageUrl;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public float getHeight() {
- return height;
- }
- public void setHeight(float height) {
- this.height = height;
- }
- public String getImageUrl() {
- return imageUrl;
- }
- public void setImageUrl(String imageUrl) {
- this.imageUrl = imageUrl;
- }
- @Override
- public String toString() {
- return “Person [id=” + id + “, userName=” + userName + “, height=”
- + height + ”, imageUrl=” + imageUrl + “]”;
- }
- }
public class Person {private int id;private String userName;private float height;private String imageUrl;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public float getHeight() {return height;}public void setHeight(float height) {this.height = height;}public String getImageUrl() {return imageUrl;}public void setImageUrl(String imageUrl) {this.imageUrl = imageUrl;}@Overridepublic String toString() {return "Person [id=" + id + ", userName=" + userName + ", height="+ height + ", imageUrl=" + imageUrl + "]";}
}
全部的编码都已经完成,最后我们再Android模拟器上运行我们的Demo实例工程,运行及操作的效果图如下:
SAX、DOM和PULL解析器的比较
- GITHUB下载
- CSDN下载
Android中XML数据解析相关推荐
- Android中Json数据解析
Android学习系列(20)--App数据格式之解析Json (很基本基础的入门,对json的基础讲的很好) http://my.eoe.cn/874311/archive/1936.html An ...
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- delphi读取xml中的内容property name传递参数_python3 Json和XML数据解析
一.Json数据解析 Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数: json.dumps(): 对数据进行编码. json.loads(): 对数据进行 ...
- android libbfaac.so,Android中Json数据读取与创建
一: Json的特性和在数据交互中的地位就不用说了,直接看案例. 首先在android studio中创建assets文件目录,用于存放Json数据文件,android studio 1.3 默认项 ...
- Android JSONObject – Android中的JSON解析
Android JSONObject is used for JSON parsing in android apps. In this tutorial we'll discuss and impl ...
- android Java开发设计模式及在android中的应用解析
android Java开发设计模式及在android中的应用解析 什么是设计模式: 可以用一句话概括设计模式---设计模式是一种利用OOP的封闭.继承和多态三大特性,同时在遵循单一职责原则.开闭原则 ...
- iOS - XML 数据解析
前言 @interface NSXMLParser : NSObjectpublic class NSXMLParser : NSObject 1.XML 数据 XML(Extensible Mark ...
- android修改xml变量值,Android中XML的基本操作(增、删、改、查)
Android中XML的一些操作 解析类: // 构造方法 public XMLParser() { } /** * 从URL获取XML使HTTP请求 * * @param url * string ...
- XML数据解析-SAX和DOM
XML:Extensible Markup language(可扩展标记语言),主流数据格式之一,可以用来存储和传输数据. StudentInfo_XML文件: <Students> &l ...
最新文章
- 大脑是怎样和身体交流的?
- 新的MOVE结构,和在项目中实际的感受
- Java 数字用二进制表示,以及原码,反码,补码、负数的二进制表示
- python数据分析numpy_Python数据分析之numpy学习
- 优化Linux系统中的服务
- 脚本其实很简单-windows配置核查程序(1)
- Hadoop YARN:调度性能优化实践【转】
- centos内核编译与其签名机制
- Java 高并发下的实践
- 【转】3.1SharePoint服务器端对象模型 之 访问文件和文件夹(Part 1)
- 大数据的搜索引擎——Elasticsearch
- linux centos java 应用服务器配置
- GNSS静态测量数据采集与内业解算
- 常用Gis通用符号库大全
- 【重要更新】TX Text Control ActiveX X16发布 | 附下载
- 赛式方法论(上):为什么你的游戏做不完、做得烂?
- 计算机金融专业亚洲大学排行,金融类专业大学排名
- java 汉字转拼音工具_java汉字转拼音工具类
- ERP现状及未来发展趋势分析?
- 论文阅读-Training a Helpful and Harmless Assistant withReinforcement Learning from Human Feedback
热门文章
- 高等组合学笔记(一)集合的计数,映射与集合的排列组合
- pycharm与python连接_pycharm2017实现python3.6与mysql的连接
- CSS3边框图片、边框阴影、文本阴影
- 浮动和清浮动,内外边距和margin的坑
- vue v-for循环动态获取_快速、简洁讲明Vue中vfor循环key的作用
- 帆软报表调用python脚本_帆软报表(finereport)实现自动滚屏效果
- sendfile实现文件服务器,sendfile
- python模块request怎么安装_安装 request模块
- python导入自己写的模块_Python:包、模块和导入
- 2008版计算机基础,计算机应用基础2008版各章课后习题解析