从网络读取数据并动态的显示在ListView中

这两天写了个小程序,使用了从网络读取xml数据,并显示在ListView中。

这里面有几个关键点:

从网络读取数据

SAX解析xml

异步填充ListView

先看下截图:

\

非常简单的界面哈

为了方便,我再自己的服务器上,放了一个xml文件,其内容主要是:

<?xml version="1.0"?>

<products>

    <product>

        <price>100</price>

        <name>android dev</name>

        <image src="image/android1.png"/>

    </product>

    <product>

        <price>100</price>

        <name>androiddev2</name>

        <image src="image/android1.png"/>

    </product>

<!-- 接着重复下去.... -->

</products>

该程序,首先用一个AsyncTask新启一个线程,来下载和解析xml;和主线程通过Handler对象来通讯。

下载XML文件

通过HTTPGet来下载xml。这时apache提供的包,需要首先包含如下包:

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.HttpStatus;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.DefaultHttpClient;

代码如下:(使用Get方法)

protected String doInBackground(String... params) {

    HttpGet httpRequest = new HttpGet(params[0]); //从url 创建一个HttpGet对象

    HttpClient httpclient = new DefaultHttpClient();

    

    //mShowHtml.setText("");

    try {

        HttpResponse httpResponse = httpclient.execute(httpRequest);

         

        if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){//获取http的返回值代码

            HttpEntity entitiy = httpResponse.getEntity();

            

            InputStream in = entitiy.getContent();//获得内容

            //解析xml,下面详述

            InputSource source = new InputSource(in);

            

            SAXParserFactory sax = SAXParserFactory.newInstance();

            XMLReader xmlReader = sax.newSAXParser().getXMLReader();

            

            xmlReader.setContentHandler(new ProductHandler());

            

            xmlReader.parse(source);

            

        }

        else {

            //return "请求失败!";

            //mShowHtml.setText("请求失败");

            //Message mymsg = mMainHandler.obtainMessage();

            //mymsg.obj = "请求失败";

            //mMainHandler.sendMessage(mymsg);

        }

    

    }catch(IOException e){

        e.printStackTrace();

    }catch(SAXException e) {

        e.printStackTrace();

    }catch(ParserConfigurationException e) {

        e.printStackTrace();

    }

    return null;

}

解析XML

使用SAX的解析方法,先包含必须得包

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

解析的代码,正如上面所示:

               

//InputSource是解析源,可以通过一个InputStream创建

urce source = new InputSource(in);                  

SAXParserFactory sax = SAXParserFactory.newInstance();

der xmlReader = sax.newSAXParser().getXMLReader();                           

xmlReader.setContentHandler(new ProductHandler());//ProductHandler是解析的句柄                        

der.parse(source);

SAX主要使用ContentHandler接口来传递解析好得数据,不过,更经常使用的是DefaultHandler

class ProductHandler extends DefaultHandler { //从DefaultHandler继承即可

    private ProductInfo curProduct;

    private String content;

    //解析到一个标签时调用

    public void startElement(String uri, String localName, String name, org.xml.sax.Attributes attributes) throws SAXException {

        if(localName.equals("product")) {//遇到product标签,进行解析

            curProduct = new ProductInfo();

        }

        else if(localName.equals("image")) {

            //set name

            curProduct.image = attributes.getValue("src");//提取image src属性

        }

        super.startElement(uri, localName, name, attributes);

    }

    

    public void endElement(String uri, String localName, String name) throws SAXException{

        if(localName.equals("product")) {//当解析到一个标签结束时,发送一个消息,把Product类作为参数传递

            //send event

            //get main handler

            Message msg = mMainHandler.obtainMessage();

            msg.obj = curProduct;

            mMainHandler.sendMessage(msg);

            //Log.i("Product:", curProduct.toString());

        }

        else if(localName.equals("name")) {

            //set name

            curProduct.name = content;//保存名字

        }

        else if(localName.equals("price")) {

            curProduct.price = Float.parseFloat(content);<span style="background-color: rgb(255, 255, 255); ">//保存价格</span>

        }

        super.endElement(uri, localName, name);

    }

    //这里获取具体的内容,是标签下保存的文本

    public void characters (char[] ch, int start, int length)  throws SAXException

    {

        content = new String(ch, start, length);

        //Log.i("Parser:" ,content);

        super.characters(ch, start, length);

    }

}

ProductInfo类的定义非常简单

class ProductInfo {

    public String name;

    public float price;

    public String image;

    public String toString() {

        return "\nName:" + name +"\nPrice :" + price + "\nImage:" + image;

    }

}

在AsyncTask中执行以上代码

public class GetHttpTask extends AsyncTask<String, Integer, String> {

    public GetHttpTask() {

    }

    

    protected void onPreExecute() { //在进入线程之前执行。该函数在调用者线程内执行

        

    }

    

    protected String doInBackground(String... params) {//线程的执行主体

        HttpGet httpRequest = new HttpGet(params[0]);

.................. //主要执行下载和解析的嗲吗

        return null;

    }

    

    protected void onPostExecute(String result) {//完成后调用

        

    }

}

在主线程中,调用GetHttpTask的execute方法就可以执行

      btn.setOnClickListener(new View.OnClickListener() {//在onCreate函数中调用

    

    @Override

    public void onClick(View v) {

        // TODO Auto-generated method stub

        httpGet();

    }

});

httpGet方法:

void httpGet() {

    GetHttpTask task = new GetHttpTask();

    task.execute("http://192.168.1.111:8080/nfcdemo/products.xml");

}

 

异步传递消息

上面的例子中,在endElement函数中,发送了消息,下面是接收消息

在主Activity中,声明了一个Handler mHandler对象,并在onCreate时,这样做

mMainHandler = new Handler() {

    public  void handleMessage(Message msg) {

        //mShowHtml.append((String)msg.obj);

        if(msg.obj != null) {

            ProductInfo prod = (ProductInfo)msg.obj;

            Log.i("Prodcut:", prod.toString());

            //mShowHtml.append(prod.toString());

            HashMap<String, Object> map = new HashMap<String, Object>();

            map.put("name", prod.name);

            map.put("price", "RMB" + prod.price);

            mlist.add(map); //mlist保存了列表的具体数据

            mProdList.notifyDataSetChanged();//mProdList是一个ListView对象,该函数引起ListView重读数据

        }

    }

};

这个过程的要点基本如上,贴上所有代码吧!关于ListView的用法,可以参考http://blog.csdn.net/hellogv/article/details/4542668

主代码:

package com.test.http;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.HttpStatus;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.DefaultHttpClient;

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListView;

import android.widget.SimpleAdapter;

public class HtmltestActivity extends Activity {

    EditText mUrlText;

    //EditText mShowHtml;

    ListView mProducts;

    Handler mMainHandler;

    SimpleAdapter mProdList;

    ArrayList<HashMap<String,Object>> mlist;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        

        mUrlText = (EditText)findViewById(R.id.eturl);

        //mShowHtml = (EditText)findViewById(R.id.etshowhtml);

        mProducts = (ListView)findViewById(R.id.productList);

        

        Button btn = (Button)findViewById(R.id.btngo);

        

        

        mlist = new ArrayList<HashMap<String, Object>>();

        mProdList = new SimpleAdapter(this,

                mlist,

                R.layout.listitem,

                new String[]{"name", "price"},

                new int[]{R.id.prd_title, R.id.prd_price}

                );

        

        mProducts.setAdapter(mProdList);

        

        

        btn.setOnClickListener(new View.OnClickListener() {

            

            @Override

            public void onClick(View v) {

                // TODO Auto-generated method stub

                httpGet();

            }

        });

        

        mMainHandler = new Handler() {

            public  void handleMessage(Message msg) {

                //mShowHtml.append((String)msg.obj);

                if(msg.obj != null) {

                    ProductInfo prod = (ProductInfo)msg.obj;

                    Log.i("Prodcut:", prod.toString());

                    //mShowHtml.append(prod.toString());

                    HashMap<String, Object> map = new HashMap<String, Object>();

                    map.put("name", prod.name);

                    map.put("price", "RMB" + prod.price);

                    mlist.add(map);

                    mProdList.notifyDataSetChanged();

                }

            }

        };

        

    }

    

    void httpGet() {

        GetHttpTask task = new GetHttpTask();

        task.execute("http://192.168.1.111:8080/nfcdemo/products.xml");

    }

    

    public class GetHttpTask extends AsyncTask<String, Integer, String> {

   

        public GetHttpTask() {

        }

        

        protected void onPreExecute() {

            

        }

        

        protected String doInBackground(String... params) {

            HttpGet httpRequest = new HttpGet(params[0]);

            HttpClient httpclient = new DefaultHttpClient();

            

            //mShowHtml.setText("");

            try {

                HttpResponse httpResponse = httpclient.execute(httpRequest);

                

                if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){

                    HttpEntity entitiy = httpResponse.getEntity();

                    

                    InputStream in = entitiy.getContent();

                    

                    InputSource source = new InputSource(in);

                    

                    SAXParserFactory sax = SAXParserFactory.newInstance();

                    XMLReader xmlReader = sax.newSAXParser().getXMLReader();

                    

                    xmlReader.setContentHandler(new ProductHandler());

                    

                    xmlReader.parse(source);

                     

                }

                else {

                    //return "请求失败!";

                    //mShowHtml.setText("请求失败");

                    //Message mymsg = mMainHandler.obtainMessage();

                    //mymsg.obj = "请求失败";

                    //mMainHandler.sendMessage(mymsg);

                }

            

            }catch(IOException e){

                e.printStackTrace();

            }catch(SAXException e) {

                e.printStackTrace();

            }catch(ParserConfigurationException e) {

                e.printStackTrace();

            }

            return null;

        }

        

        protected void onPostExecute(String result) {

            //mShowHtml.setText(result);

        }

    }

    

    class ProductInfo {

        public String name;

        public float price;

        public String image;

        public String toString() {

            return "\nName:" + name +"\nPrice :" + price + "\nImage:" + image;

        }

    }

    

    class ProductHandler extends DefaultHandler {

        private ProductInfo curProduct;

        private String content;

        

        public void startElement(String uri, String localName, String name, org.xml.sax.Attributes attributes) throws SAXException {

            if(localName.equals("product")) {

                curProduct = new ProductInfo();

            }

            else if(localName.equals("image")) {

                //set name

                curProduct.image = attributes.getValue("src");

            }

            super.startElement(uri, localName, name, attributes);

        }

        

        public void endElement(String uri, String localName, String name) throws SAXException{ 

            if(localName.equals("product")) {

                //send event

                //get main handler

                Message msg = mMainHandler.obtainMessage();

                msg.obj = curProduct;

                mMainHandler.sendMessage(msg);

                //Log.i("Product:", curProduct.toString());

            }

            else if(localName.equals("name")) {

                //set name

                curProduct.name = content;

            }

            else if(localName.equals("price")) {

                curProduct.price = Float.parseFloat(content);

            }

            super.endElement(uri, localName, name);

        }

        

        public void characters (char[] ch, int start, int length)  throws SAXException

        {

            content = new String(ch, start, length);

            //Log.i("Parser:" ,content);

            super.characters(ch, start, length);

        }

    }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >

    <LinearLayout

        android:id="@+id/linearLayout1"

        android:layout_width="match_parent"

        android:layout_height="wrap_content" >

        <EditText

            android:id="@+id/eturl"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:layout_weight="1" >

            <requestFocus />

        </EditText>

        <Button

            android:id="@+id/btngo"

            android:layout_width="100dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="Go!" />

    </LinearLayout>

    <ListView

        android:id="@+id/productList"

        android:layout_width="match_parent"

        android:layout_height="match_parent" >

    </ListView>

</LinearLayout>

listitem.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

    <ImageView

        android:id="@+id/product_icon"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentLeft="true"

        android:layout_alignParentTop="true"

        android:src="@drawable/ic_launcher" />

    <TextView

        android:id="@+id/prd_title"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentTop="true"

        android:layout_toRightOf="@+id/product_icon"

        android:text="TextView" />

    <TextView

        android:id="@+id/prd_price"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentRight="true"

        android:layout_alignParentTop="true"

        android:text="TextView" />

</RelativeLayout>  

doon的专栏

posted @ 2012-02-15 16:27  子福当自强  阅读(...)  评论(... 编辑 收藏
悟道2012