首页 > 代码库 > Android ListView从网络获取图片及文字显示

Android ListView从网络获取图片及文字显示

上一篇文章说的是ListView展示本地的图片以及文本,这一篇说一下如何从网络获取图片以及文本来显示。事实上,一般是先获取Josn或sml数据,然后解释显示。我们先从网上获取xml,然后对其进行解析,最后显示在ListView上。具体步骤:

  • 客户端发出请求,获取xml
  • 客户端异步解析xml
  • ListView将解析完的数据显示

      一、Android客户端

                                                                           

     (1)xml布局文件

        mainxml,就是一个ListView。     

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical">  
  6.       
  7.     <ListView  
  8.         android:id="@+id/list"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:divider="#b5b5b5"  
  12.         android:dividerHeight="1dp"  
  13.         android:listSelector="@drawable/list_selector" />  
  14.   
  15. </LinearLayout>  

       ListView的每一行的布局,list_raw.xml,看一下结构图:

                                                         

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:background="@drawable/list_selector"  
  6.     android:orientation="horizontal"  
  7.     android:padding="5dip" >  
  8.   
  9.     <!--  ListView最左边的缩略图 -->  
  10.     <LinearLayout android:id="@+id/thumbnail"   
  11.         android:layout_width="wrap_content"  
  12.         android:layout_height="wrap_content"  
  13.         android:padding="3dip"        
  14.         android:layout_alignParentLeft="true"  
  15.         android:background="@drawable/image_bg"   
  16.         android:layout_marginRight="5dip">  
  17.           
  18.         <ImageView       
  19.             android:id="@+id/list_image"     
  20.             android:layout_width="50dip"  
  21.             android:layout_height="50dip"  
  22.             android:src=http://www.mamicode.com/"@drawable/rihanna"/>  
  23.           
  24.     </LinearLayout>  
  25.       
  26.     <!-- 歌曲名-->  
  27.     <TextView  
  28.         android:id="@+id/title"  
  29.         android:layout_width="wrap_content"  
  30.         android:layout_height="wrap_content"  
  31.         android:layout_alignTop="@+id/thumbnail"  
  32.         android:layout_toRightOf="@+id/thumbnail"  
  33.         android:text="Rihanna Love the way lie"  
  34.         android:textColor="#040404"  
  35.         android:typeface="sans"   
  36.         android:textSize="15dip"  
  37.         android:textStyle="bold"/>  
  38.   
  39.     <!-- 歌手名 -->  
  40.     <TextView  
  41.         android:id="@+id/artist"  
  42.         android:layout_width="fill_parent"  
  43.         android:layout_height="wrap_content"  
  44.         android:layout_below="@id/title"  
  45.         android:textColor="#343434"  
  46.         android:textSize="10dip"  
  47.         android:layout_marginTop="1dip"  
  48.         android:layout_toRightOf="@+id/thumbnail"  
  49.         android:text="Just gona stand there and ..." />  
  50.   
  51.     <!-- 歌曲播放时间 -->  
  52.     <TextView  
  53.         android:id="@+id/duration"  
  54.         android:layout_width="wrap_content"  
  55.         android:layout_height="wrap_content"  
  56.         android:layout_alignParentRight="true"  
  57.         android:layout_alignTop="@id/title"  
  58.         android:gravity="right"  
  59.         android:text="5:45"  
  60.         android:layout_marginRight="5dip"  
  61.         android:textSize="10dip"  
  62.         android:textColor="#10bcc9"  
  63.         android:textStyle="bold"/>  
  64.         
  65.      <!-- 进入播放 -->      
  66.      <ImageView android:layout_width="wrap_content"  
  67.         android:layout_height="wrap_content"  
  68.         android:src=http://www.mamicode.com/"@drawable/arrow"  
  69.         android:layout_alignParentRight="true"  
  70.         android:layout_centerVertical="true"/>  
  71.   
  72. </RelativeLayout>  

      另外我们打算使用几个特效,一个是当点击列表项目的时候,项目背景色改变,其实就是一个selector;另一个就是用shape美化视觉效果,具体看xml代码:

      1.list_selector.xml      

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3. <!-- Selector style for listrow -->  
  4. <item   
  5.  android:state_selected="false"  
  6.     android:state_pressed="false"   
  7.     android:drawable="@drawable/gradient_bg" />  
  8. <item android:state_pressed="true"   
  9.     android:drawable="@drawable/gradient_bg_hover" />  
  10. <item android:state_selected="true"  
  11.  android:state_pressed="false"   
  12.     android:drawable="@drawable/gradient_bg_hover" />  
  13. </selector>  

                                                         

 2.gradient_bg.xml,是默认背景梯度风格  

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:shape="rectangle">  
  4.   <!--  Gradient Bg for listrow -->  
  5.   <gradient  
  6.       android:startColor="#f1f1f2"  
  7.       android:centerColor="#e7e7e8"  
  8.       android:endColor="#cfcfcf"  
  9.       android:angle="270" />  
  10. </shape>  

         3.gradient_bg_hover.xml 梯度风格在悬停状态

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:shape="rectangle">  
  4.   <!-- Gradient BgColor for listrow Selected -->  
  5.   <gradient  
  6.       android:startColor="#18d7e5"  
  7.       android:centerColor="#16cedb"  
  8.       android:endColor="#09adb9"  
  9.       android:angle="270" />  
  10.     
  11. </shape>  


          4.image_bg.xml 在图片周围的白色边条

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <item>  
  4.       <shape   
  5.         android:shape="rectangle">  
  6.             <stroke android:width="1dp" android:color="#dbdbdc" />  
  7.             <solid android:color="#FFFFFF" />  
  8.         </shape>  
  9.    </item>  
  10. </layer-list>  

          以上效果基本上都用到了shape,对此不了解的可以去查看相关资料。上面就是全部的xml布局文件,下面将开始写代码。

   (2)主要代码

            代码部分主要涉及到一下几个功能,重写ListView的适配器(BaseAdapter),从网络获取图片,图片缓存的处理,xml的解析。

            ①重写ListView的适配器,这部分可以参考上一篇文章,LazyAdapter.java          

[java] view plaincopy
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8. import android.widget.BaseAdapter;  
  9. import android.widget.ImageView;  
  10. import android.widget.TextView;  
  11.   
  12. public class LazyAdapter extends BaseAdapter {  
  13.       
  14.     private Activity activity;  
  15.     private ArrayList<HashMap<String, String>> data;  
  16.     private static LayoutInflater inflater=null;  
  17.     public ImageLoader imageLoader; //用来下载图片的类,后面有介绍  
  18.       
  19.     public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {  
  20.         activity = a;  
  21.         data=http://www.mamicode.com/d;
  22.         inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  23.         imageLoader=new ImageLoader(activity.getApplicationContext());  
  24.     }  
  25.   
  26.     public int getCount() {  
  27.         return data.size();  
  28.     }  
  29.   
  30.     public Object getItem(int position) {  
  31.         return position;  
  32.     }  
  33.   
  34.     public long getItemId(int position) {  
  35.         return position;  
  36.     }  
  37.       
  38.     public View getView(int position, View convertView, ViewGroup parent) {  
  39.         View vi=convertView;  
  40.         if(convertView==null)  
  41.             vi = inflater.inflate(R.layout.list_row, null);  
  42.   
  43.         TextView title = (TextView)vi.findViewById(R.id.title); // 标题  
  44.         TextView artist = (TextView)vi.findViewById(R.id.artist); // 歌手名  
  45.         TextView duration = (TextView)vi.findViewById(R.id.duration); // 时长  
  46.         ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // 缩略图  
  47.           
  48.         HashMap<String, String> song = new HashMap<String, String>();  
  49.         song = data.get(position);  
  50.           
  51.         // 设置ListView的相关值  
  52.         title.setText(song.get(CustomizedListView.KEY_TITLE));  
  53.         artist.setText(song.get(CustomizedListView.KEY_ARTIST));  
  54.         duration.setText(song.get(CustomizedListView.KEY_DURATION));  
  55.         imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);  
  56.         return vi;  
  57.   <em>  }  
  58. }</em>  

         ②网络获取图片的类,ImageLoader.java:     

[java] view plaincopy
  1. import java.io.File;   
  2. import java.io.FileInputStream;   
  3. import java.io.FileNotFoundException;   
  4. import java.io.FileOutputStream;   
  5. import java.io.InputStream;   
  6. import java.io.OutputStream;   
  7. import java.net.HttpURLConnection;   
  8. import java.net.URL;   
  9. import java.util.Collections;   
  10. import java.util.Map;   
  11. import java.util.WeakHashMap;   
  12. import java.util.concurrent.ExecutorService;   
  13. import java.util.concurrent.Executors;    
  14. import android.app.Activity;   
  15. import android.content.Context;   
  16. import android.graphics.Bitmap;   
  17. import android.graphics.BitmapFactory;   
  18. import android.widget.ImageView;   
  19.     
  20. public class ImageLoader {   
  21.     
  22.     MemoryCache memoryCache=new MemoryCache();   
  23.     FileCache fileCache;   
  24.     private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());   
  25.     ExecutorService executorService;    
  26.     
  27.     public ImageLoader(Context context){   
  28.         fileCache=new FileCache(context);   
  29.         executorService=Executors.newFixedThreadPool(5);   
  30.     }   
  31.     
  32.     final int stub_id = R.drawable.no_image;   
  33.     public void DisplayImage(String url, ImageView imageView)   
  34.     {   
  35.         imageViews.put(imageView, url);   
  36.         Bitmap bitmap=memoryCache.get(url);   
  37.         if(bitmap!=null)   
  38.             imageView.setImageBitmap(bitmap);   
  39.         else  
  40.         {   
  41.             queuePhoto(url, imageView);   
  42.             imageView.setImageResource(stub_id);   
  43.         }   
  44.     }   
  45.     
  46.     private void queuePhoto(String url, ImageView imageView)   
  47.     {   
  48.         PhotoToLoad p=new PhotoToLoad(url, imageView);   
  49.         executorService.submit(new PhotosLoader(p));   
  50.     }   
  51.     
  52.     private Bitmap getBitmap(String url)   
  53.     {   
  54.         File f=fileCache.getFile(url);   
  55.     
  56.         //从sd卡  
  57.         Bitmap b = decodeFile(f);   
  58.         if(b!=null)   
  59.             return b;   
  60.     
  61.         //从网络  
  62.         try {   
  63.             Bitmap bitmap=null;   
  64.             URL imageUrl = new URL(url);   
  65.             HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();   
  66.             conn.setConnectTimeout(30000);   
  67.             conn.setReadTimeout(30000);   
  68.             conn.setInstanceFollowRedirects(true);   
  69.             InputStream is=conn.getInputStream();   
  70.             OutputStream os = new FileOutputStream(f);   
  71.             Utils.CopyStream(is, os);   
  72.             os.close();   
  73.             bitmap = decodeFile(f);   
  74.             return bitmap;   
  75.         } catch (Exception ex){   
  76.            ex.printStackTrace();   
  77.            return null;   
  78.         }   
  79.     }   
  80.     
  81.     //解码图像用来减少内存消耗  
  82.     private Bitmap decodeFile(File f){   
  83.         try {   
  84.             //解码图像大小  
  85.             BitmapFactory.Options o = new BitmapFactory.Options();   
  86.             o.inJustDecodeBounds = true;   
  87.             BitmapFactory.decodeStream(new FileInputStream(f),null,o);   
  88.     
  89.             //找到正确的刻度值,它应该是2的幂。  
  90.             final int REQUIRED_SIZE=70;   
  91.             int width_tmp=o.outWidth, height_tmp=o.outHeight;   
  92.             int scale=1;   
  93.             while(true){   
  94.                 if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)   
  95.                     break;   
  96.                 width_tmp/=2;   
  97.                 height_tmp/=2;   
  98.                 scale*=2;   
  99.             }   
  100.     
  101.             BitmapFactory.Options o2 = new BitmapFactory.Options();   
  102.             o2.inSampleSize=scale;   
  103.             return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);   
  104.         } catch (FileNotFoundException e) {}   
  105.         return null;   
  106.     }   
  107.     
  108.     /任务队列  
  109.     private class PhotoToLoad   
  110.     {   
  111.         public String url;   
  112.         public ImageView imageView;   
  113.         public PhotoToLoad(String u, ImageView i){   
  114.             url=u;   
  115.             imageView=i;   
  116.         }   
  117.     }   
  118.     
  119.     class PhotosLoader implements Runnable {   
  120.         PhotoToLoad photoToLoad;   
  121.         PhotosLoader(PhotoToLoad photoToLoad){   
  122.             this.photoToLoad=photoToLoad;   
  123.         }   
  124.     
  125.         @Override  
  126.         public void run() {   
  127.             if(imageViewReused(photoToLoad))   
  128.                 return;   
  129.             Bitmap bmp=getBitmap(photoToLoad.url);   
  130.             memoryCache.put(photoToLoad.url, bmp);   
  131.             if(imageViewReused(photoToLoad))   
  132.                 return;   
  133.             BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);   
  134.             Activity a=(Activity)photoToLoad.imageView.getContext();   
  135.             a.runOnUiThread(bd);   
  136.         }   
  137.     }   
  138.     
  139.     boolean imageViewReused(PhotoToLoad photoToLoad){   
  140.         String tag=imageViews.get(photoToLoad.imageView);   
  141.         if(tag==null || !tag.equals(photoToLoad.url))   
  142.             return true;   
  143.         return false;   
  144.     }   
  145.     
  146.     //用于显示位图在UI线程  
  147.     class BitmapDisplayer implements Runnable   
  148.     {   
  149.         Bitmap bitmap;   
  150.         PhotoToLoad photoToLoad;   
  151.         public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}   
  152.         public void run()   
  153.         {   
  154.             if(imageViewReused(photoToLoad))   
  155.                 return;   
  156.             if(bitmap!=null)   
  157.                 photoToLoad.imageView.setImageBitmap(bitmap);   
  158.             else  
  159.                 photoToLoad.imageView.setImageResource(stub_id);   
  160.         }   
  161.     }   
  162.     
  163.     public void clearCache() {   
  164.         memoryCache.clear();   
  165.         fileCache.clear();   
  166.     }   
  167.     
  168. }   

       ③xml解析,xml的解析有很多方法,这里采用进行dom方式的xml解析。

[java] view plaincopy
  1. import java.io.IOException;   
  2. import java.io.StringReader;   
  3. import java.io.UnsupportedEncodingException;     
  4. import javax.xml.parsers.DocumentBuilder;   
  5. import javax.xml.parsers.DocumentBuilderFactory;   
  6. import javax.xml.parsers.ParserConfigurationException;     
  7. import org.apache.http.HttpEntity;   
  8. import org.apache.http.HttpResponse;   
  9. import org.apache.http.client.ClientProtocolException;   
  10. import org.apache.http.client.methods.HttpPost;   
  11. import org.apache.http.impl.client.DefaultHttpClient;   
  12. import org.apache.http.util.EntityUtils;   
  13. import org.w3c.dom.Document;   
  14. import org.w3c.dom.Element;   
  15. import org.w3c.dom.Node;   
  16. import org.w3c.dom.NodeList;   
  17. import org.xml.sax.InputSource;   
  18. import org.xml.sax.SAXException;    
  19. import android.util.Log;   
  20.     
  21. public class XMLParser {   
  22.     
  23.     // 构造方法  
  24.     public XMLParser() {   
  25.     
  26.     }   
  27.     
  28.     /**  
  29.      * 从URL获取XML使HTTP请求 
  30.      * @param url string  
  31.      * */  
  32.     public String getXmlFromUrl(String url) {   
  33.         String xml = null;   
  34.     
  35.         try {   
  36.             // defaultHttpClient   
  37.             DefaultHttpClient httpClient = new DefaultHttpClient();   
  38.             HttpPost httpPost = new HttpPost(url);   
  39.     
  40.             HttpResponse httpResponse = httpClient.execute(httpPost);   
  41.             HttpEntity httpEntity = httpResponse.getEntity();   
  42.             xml = EntityUtils.toString(httpEntity);   
  43.     
  44.         } catch (UnsupportedEncodingException e) {   
  45.             e.printStackTrace();   
  46.         } catch (ClientProtocolException e) {   
  47.             e.printStackTrace();   
  48.         } catch (IOException e) {   
  49.             e.printStackTrace();   
  50.         }   
  51.         return xml;   
  52.     }   
  53.     
  54.     /**  
  55.      * 获取XML DOM元素 
  56.      * @param XML string  
  57.      * */  
  58.     public Document getDomElement(String xml){   
  59.         Document doc = null;   
  60.         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();   
  61.         try {   
  62.     
  63.             DocumentBuilder db = dbf.newDocumentBuilder();   
  64.     
  65.             InputSource is = new InputSource();   
  66.                 is.setCharacterStream(new StringReader(xml));   
  67.                 doc = db.parse(is);    
  68.     
  69.             } catch (ParserConfigurationException e) {   
  70.                 Log.e("Error: ", e.getMessage());   
  71.                 return null;   
  72.             } catch (SAXException e) {   
  73.                 Log.e("Error: ", e.getMessage());   
  74.                 return null;   
  75.             } catch (IOException e) {   
  76.                 Log.e("Error: ", e.getMessage());   
  77.                 return null;   
  78.             }   
  79.     
  80.             return doc;   
  81.     }   
  82.     
  83.     /** 获取节点值 
  84.       * @param elem element  
  85.       */  
  86.      public final String getElementValue( Node elem ) {   
  87.          Node child;   
  88.          if( elem != null){   
  89.              if (elem.hasChildNodes()){   
  90.                  for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){   
  91.                      if( child.getNodeType() == Node.TEXT_NODE  ){   
  92.                          return child.getNodeValue();   
  93.                      }   
  94.                  }   
  95.              }   
  96.          }   
  97.          return "";   
  98.      }   
  99.     
  100.      /**  
  101.       * 获取节点值 
  102.       * @param Element node  
  103.       * @param key string  
  104.       * */  
  105.      public String getValue(Element item, String str) {   
  106.             NodeList n = item.getElementsByTagName(str);   
  107.             return this.getElementValue(n.item(0));   
  108.         }   
  109. }  

       ④程序缓存的处理,主要是内存缓存+文件缓存。内存缓存中网上很多是采用SoftReference来防止堆溢出:

     MemoryCache.java:

[java] view plaincopy
  1. import java.lang.ref.SoftReference;  
  2. import java.util.Collections;  
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import android.graphics.Bitmap;  
  6.   
  7. public class MemoryCache {  
  8.     private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());//软引用  
  9.       
  10.     public Bitmap get(String id){  
  11.         if(!cache.containsKey(id))  
  12.             return null;  
  13.         SoftReference<Bitmap> ref=cache.get(id);  
  14.         return ref.get();  
  15.     }  
  16.       
  17.     public void put(String id, Bitmap bitmap){  
  18.         cache.put(id, new SoftReference<Bitmap>(bitmap));  
  19.     }  
  20.   
  21.     public void clear() {  
  22.         cache.clear();  
  23.     }  
  24. }  

      FileCache.java

[java] view plaincopy
  1. import java.io.File;  
  2. import android.content.Context;  
  3.   
  4. public class FileCache {  
  5.       
  6.     private File cacheDir;  
  7.       
  8.     public FileCache(Context context){  
  9.         //找一个用来缓存图片的路径  
  10.         if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))  
  11.             cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList");  
  12.         else  
  13.             cacheDir=context.getCacheDir();  
  14.         if(!cacheDir.exists())  
  15.             cacheDir.mkdirs();  
  16.     }  
  17.       
  18.     public File getFile(String url){  
  19.           
  20.         String filename=String.valueOf(url.hashCode());  
  21.         File f = new File(cacheDir, filename);  
  22.         return f;  
  23.           
  24.     }  
  25.       
  26.     public void clear(){  
  27.         File[] files=cacheDir.listFiles();  
  28.         if(files==null)  
  29.             return;  
  30.         for(File f:files)  
  31.             f.delete();  
  32.     }  
  33.   
  34. }  

          ⑤还有一个读取流的工具类,Utils.java:

[java] view plaincopy
  1. import java.io.InputStream;  
  2. import java.io.OutputStream;  
  3.   
  4.   
  5. public class Utils {  
  6.     public static void CopyStream(InputStream is, OutputStream os)  
  7.     {  
  8.         final int buffer_size=1024;  
  9.         try  
  10.         {  
  11.             byte[] bytes=new byte[buffer_size];  
  12.             for(;;)  
  13.             {  
  14.               int count=is.read(bytes, 0, buffer_size);  
  15.               if(count==-1)  
  16.                   break;  
  17.               os.write(bytes, 0, count);  
  18.               is.close();  
  19.               os.close();  
  20.             }  
  21.         }  
  22.         catch(Exception ex){}  
  23.     }  
  24. }  

还可以像下面这样表达,方法是一样的,就是表达形式上不同:

[java] view plaincopy
  1. public static byte[] readStream(InputStream inStream) throws Exception{  
  2.   
  3. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
  4. byte[] buffer = new byte[1024];  
  5. int len = -1;  
  6. while( (len=inStream.read(buffer)) != -1){  
  7. outSteam.write(buffer, 0, len);  
  8.   
  9. }  
  10. outSteam.close();  
  11. inStream.close();  
  12. return outSteam.toByteArray();  
  13.   
  14. }  
  15. }  

      最后就是主Activity的代码了,

[java] view plaincopy
  1. package com.example.androidhive;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import org.w3c.dom.Document;  
  6. import org.w3c.dom.Element;  
  7. import org.w3c.dom.NodeList;  
  8. import android.app.Activity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.widget.AdapterView;  
  12. import android.widget.AdapterView.OnItemClickListener;  
  13. import android.widget.ListView;  
  14.   
  15. public class CustomizedListView extends Activity {  
  16.     // 所有的静态变量  
  17.     static final String URL = "http://api.androidhive.info/music/music.xml";//xml目的地址,打开地址看一下  
  18.     // XML 节点  
  19.     static final String KEY_SONG = "song"; // parent node  
  20.     static final String KEY_ID = "id";  
  21.     static final String KEY_TITLE = "title";  
  22.     static final String KEY_ARTIST = "artist";  
  23.     static final String KEY_DURATION = "duration";  
  24.     static final String KEY_THUMB_URL = "thumb_url";  
  25.       
  26.     ListView list;  
  27.         LazyAdapter adapter;  
  28.   
  29.     @Override  
  30.     public void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.main);  
  33.           
  34.   
  35.         ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();  
  36.   
  37.         XMLParser parser = new XMLParser();  
  38.         String xml = parser.getXmlFromUrl(URL); // 从网络获取xml  
  39.         Document doc = parser.getDomElement(xml); // 获取 DOM 节点  
  40.           
  41.         NodeList nl = doc.getElementsByTagName(KEY_SONG);  
  42.         // 循环遍历所有的歌节点 <song>  
  43.         for (int i = 0; i < nl.getLength(); i++) {  
  44.             // 新建一个 HashMap  
  45.             HashMap<String, String> map = new HashMap<String, String>();  
  46.             Element e = (Element) nl.item(i);  
  47.             //每个子节点添加到HashMap关键= >值  
  48.             map.put(KEY_ID, parser.getValue(e, KEY_ID));  
  49.             map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));  
  50.             map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));  
  51.             map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));  
  52.             map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));  
  53.   
  54.             // HashList添加到数组列表  
  55.             songsList.add(map);  
  56.         }  
  57.           
  58.   
  59.         list=(ListView)findViewById(R.id.list);  
  60.           
  61.           
  62.               adapter=new LazyAdapter(this, songsList);          
  63.               list.setAdapter(adapter);  
  64.           
  65.   
  66.         //为单一列表行添加单击事件  
  67.   
  68.         list.setOnItemClickListener(new OnItemClickListener() {  
  69.   
  70.             @Override  
  71.             public void onItemClick(AdapterView<?> parent, View view,  
  72.                     int position, long id) {  
  73.                               
  74.                         //这里可以自由发挥,比如播放一首歌曲等等  
  75.             }  
  76.         });       
  77.     }     
  78. }  

      最后看一下效果: