您的位置:首页 > 理论基础 > 计算机网络

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

2017-07-06 18:20 337 查看
转:http://blog.csdn.net/wangjinyu501/article/details/8219317/

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

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

      一、Android客户端

                                                                           


     (1)xml布局文件

        mainxml,就是一个ListView。     

[java]
view plain
copy

print?

<?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">  
      
    <ListView  
        android:id="@+id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:divider="#b5b5b5"  
        android:dividerHeight="1dp"  
        android:listSelector="@drawable/list_selector" />  
  
</LinearLayout>  

<?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">

<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:listSelector="@drawable/list_selector" />

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

                                                         


[java]
view plain
copy

print?

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:background="@drawable/list_selector"  
    android:orientation="horizontal"  
    android:padding="5dip" >  
  
    <!--  ListView最左边的缩略图 -->  
    <LinearLayout android:id="@+id/thumbnail"   
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:padding="3dip"        
        android:layout_alignParentLeft="true"  
        android:background="@drawable/image_bg"   
        android:layout_marginRight="5dip">  
          
        <ImageView       
            android:id="@+id/list_image"     
            android:layout_width="50dip"  
            android:layout_height="50dip"  
            android:src="@drawable/rihanna"/>  
          
    </LinearLayout>  
      
    <!-- 歌曲名-->  
    <TextView  
        android:id="@+id/title"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_alignTop="@+id/thumbnail"  
        android:layout_toRightOf="@+id/thumbnail"  
        android:text="Rihanna Love the way lie"  
        android:textColor="#040404"  
        android:typeface="sans"   
        android:textSize="15dip"  
        android:textStyle="bold"/>  
  
    <!-- 歌手名 -->  
    <TextView  
        android:id="@+id/artist"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:layout_below="@id/title"  
        android:textColor="#343434"  
        android:textSize="10dip"  
        android:layout_marginTop="1dip"  
        android:layout_toRightOf="@+id/thumbnail"  
        android:text="Just gona stand there and ..." />  
  
    <!-- 歌曲播放时间 -->  
    <TextView  
        android:id="@+id/duration"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_alignParentRight="true"  
        android:layout_alignTop="@id/title"  
        android:gravity="right"  
        android:text="5:45"  
        android:layout_marginRight="5dip"  
        android:textSize="10dip"  
        android:textColor="#10bcc9"  
        android:textStyle="bold"/>  
        
     <!-- 进入播放 -->      
     <ImageView android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:src="@drawable/arrow"  
        android:layout_alignParentRight="true"  
        android:layout_centerVertical="true"/>  
  
</RelativeLayout>  

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >

<!--  ListView最左边的缩略图 -->
<LinearLayout android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:layout_alignParentLeft="true"
android:background="@drawable/image_bg"
android:layout_marginRight="5dip">

<ImageView
android:id="@+id/list_image"
android:layout_width="50dip"
android:layout_height="50dip"
android:src="@drawable/rihanna"/>

</LinearLayout>

<!-- 歌曲名-->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/thumbnail"
android:layout_toRightOf="@+id/thumbnail"
android:text="Rihanna Love the way lie"
android:textColor="#040404"
android:typeface="sans"
android:textSize="15dip"
android:textStyle="bold"/>

<!-- 歌手名 -->
<TextView
android:id="@+id/artist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:textColor="#343434"
android:textSize="10dip"
android:layout_marginTop="1dip"
android:layout_toRightOf="@+id/thumbnail"
android:text="Just gona stand there and ..." />

<!-- 歌曲播放时间 -->
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/title"
android:gravity="right"
android:text="5:45"
android:layout_marginRight="5dip"
android:textSize="10dip"
android:textColor="#10bcc9"
android:textStyle="bold"/>

<!-- 进入播放 -->
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/arrow"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>

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

[java]
view plain
copy

print?

<?xml version="1.0" encoding="utf-8"?>  
<selector xmlns:android="http://schemas.android.com/apk/res/android">  
<!-- Selector style for listrow -->  
<item   
 android:state_selected="false"  
    android:state_pressed="false"   
    android:drawable="@drawable/gradient_bg" />  
<item android:state_pressed="true"   
    android:drawable="@drawable/gradient_bg_hover" />  
<item android:state_selected="true"  
 android:state_pressed="false"   
    android:drawable="@drawable/gradient_bg_hover" />  
</selector>  

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="@drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="@drawable/gradient_bg_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="@drawable/gradient_bg_hover" />
</selector>
                                                         


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

[java]
view plain
copy

print?

<?xml version="1.0" encoding="utf-8"?>  
<shape xmlns:android="http://schemas.android.com/apk/res/android"  
    android:shape="rectangle">  
  <!--  Gradient Bg for listrow -->  
  <gradient  
      android:startColor="#f1f1f2"  
      android:centerColor="#e7e7e8"  
      android:endColor="#cfcfcf"  
      android:angle="270" />  
</shape>  

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--  Gradient Bg for listrow -->
<gradient
android:startColor="#f1f1f2"
android:centerColor="#e7e7e8"
android:endColor="#cfcfcf"
android:angle="270" />
</shape>
         3.gradient_bg_hover.xml 梯度风格在悬停状态

[java]
view plain
copy

print?

<?xml version="1.0" encoding="utf-8"?>  
<shape xmlns:android="http://schemas.android.com/apk/res/android"  
    android:shape="rectangle">  
  <!-- Gradient BgColor for listrow Selected -->  
  <gradient  
      android:startColor="#18d7e5"  
      android:centerColor="#16cedb"  
      android:endColor="#09adb9"  
      android:angle="270" />  
    
</shape>  

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- Gradient BgColor for listrow Selected -->
<gradient
android:startColor="#18d7e5"
android:centerColor="#16cedb"
android:endColor="#09adb9"
android:angle="270" />

</shape>


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

[java]
view plain
copy

print?

<?xml version="1.0" encoding="utf-8"?>  
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >  
    <item>  
      <shape   
        android:shape="rectangle">  
            <stroke android:width="1dp" android:color="#dbdbdc" />  
            <solid android:color="#FFFFFF" />  
        </shape>  
   </item>  
</layer-list>  

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
android:shape="rectangle">
<stroke android:width="1dp" android:color="#dbdbdc" />
<solid android:color="#FFFFFF" />
</shape>
</item>
</layer-list>
          以上效果基本上都用到了shape,对此不了解的可以去查看相关资料。上面就是全部的xml布局文件,下面将开始写代码。

   (2)主要代码

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

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

[java]
view plain
copy

print?

import java.util.ArrayList;  
import java.util.HashMap;  
import android.app.Activity;  
import android.content.Context;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.ImageView;  
import android.widget.TextView;  
  
public class LazyAdapter extends BaseAdapter {  
      
    private Activity activity;  
    private ArrayList<HashMap<String, String>> data;  
    private static LayoutInflater inflater=null;  
    public ImageLoader imageLoader; //用来下载图片的类,后面有介绍  
      
    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {  
        activity = a;  
        data=d;  
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        imageLoader=new ImageLoader(activity.getApplicationContext());  
    }  
  
    public int getCount() {  
        return data.size();  
    }  
  
    public Object getItem(int position) {  
        return position;  
    }  
  
    public long getItemId(int position) {  
        return position;  
    }  
      
    public View getView(int position, View convertView, ViewGroup parent) {  
        View vi=convertView;  
        if(convertView==null)  
            vi = inflater.inflate(R.layout.list_row, null);  
  
        TextView title = (TextView)vi.findViewById(R.id.title); // 标题  
        TextView artist = (TextView)vi.findViewById(R.id.artist); // 歌手名  
        TextView duration = (TextView)vi.findViewById(R.id.duration); // 时长  
        ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // 缩略图  
          
        HashMap<String, String> song = new HashMap<String, String>();  
        song = data.get(position);  
          
        // 设置ListView的相关值  
        title.setText(song.get(CustomizedListView.KEY_TITLE));  
        artist.setText(song.get(CustomizedListView.KEY_ARTIST));  
        duration.setText(song.get(CustomizedListView.KEY_DURATION));  
        imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);  
        return vi;  
  <em>  }  
}</em>  

import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class LazyAdapter extends BaseAdapter {

private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader; //用来下载图片的类,后面有介绍

public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}

public int getCount() {
return data.size();
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);

TextView title = (TextView)vi.findViewById(R.id.title); // 标题
TextView artist = (TextView)vi.findViewById(R.id.artist); // 歌手名
TextView duration = (TextView)vi.findViewById(R.id.duration); // 时长
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // 缩略图

HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);

// 设置ListView的相关值
title.setText(song.get(CustomizedListView.KEY_TITLE));
artist.setText(song.get(CustomizedListView.KEY_ARTIST));
duration.setText(song.get(CustomizedListView.KEY_DURATION));
imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);
return vi;
}
}

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

[java]
view plain
copy

print?

import java.io.File;   
import java.io.FileInputStream;   
import java.io.FileNotFoundException;   
import java.io.FileOutputStream;   
import java.io.InputStream;   
import java.io.OutputStream;   
import java.net.HttpURLConnection;   
import java.net.URL;   
import java.util.Collections;   
import java.util.Map;   
import java.util.WeakHashMap;   
import java.util.concurrent.ExecutorService;   
import java.util.concurrent.Executors;    
import android.app.Activity;   
import android.content.Context;   
import android.graphics.Bitmap;   
import android.graphics.BitmapFactory;   
import android.widget.ImageView;   
    
public class ImageLoader {   
    
    MemoryCache memoryCache=new MemoryCache();   
    FileCache fileCache;   
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());   
    ExecutorService executorService;    
    
    public ImageLoader(Context context){   
        fileCache=new FileCache(context);   
        executorService=Executors.newFixedThreadPool(5);   
    }   
    
    final int stub_id = R.drawable.no_image;   
    public void DisplayImage(String url, ImageView imageView)   
    {   
        imageViews.put(imageView, url);   
        Bitmap bitmap=memoryCache.get(url);   
        if(bitmap!=null)   
            imageView.setImageBitmap(bitmap);   
        else  
        {   
            queuePhoto(url, imageView);   
            imageView.setImageResource(stub_id);   
        }   
    }   
    
    private void queuePhoto(String url, ImageView imageView)   
    {   
        PhotoToLoad p=new PhotoToLoad(url, imageView);   
        executorService.submit(new PhotosLoader(p));   
    }   
    
    private Bitmap getBitmap(String url)   
    {   
        File f=fileCache.getFile(url);   
    
        //从sd卡  
        Bitmap b = decodeFile(f);   
        if(b!=null)   
            return b;   
    
        //从网络  
        try {   
            Bitmap bitmap=null;   
            URL imageUrl = new URL(url);   
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();   
            conn.setConnectTimeout(30000);   
            conn.setReadTimeout(30000);   
            conn.setInstanceFollowRedirects(true);   
            InputStream is=conn.getInputStream();   
            OutputStream os = new FileOutputStream(f);   
            Utils.CopyStream(is, os);   
            os.close();   
            bitmap = decodeFile(f);   
            return bitmap;   
        } catch (Exception ex){   
           ex.printStackTrace();   
           return null;   
        }   
    }   
    
    //解码图像用来减少内存消耗  
    private Bitmap decodeFile(File f){   
        try {   
            //解码图像大小  
            BitmapFactory.Options o = new BitmapFactory.Options();   
            o.inJustDecodeBounds = true;   
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);   
    
            //找到正确的刻度值,它应该是2的幂。  
            final int REQUIRED_SIZE=70;   
            int width_tmp=o.outWidth, height_tmp=o.outHeight;   
            int scale=1;   
            while(true){   
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)   
                    break;   
                width_tmp/=2;   
                height_tmp/=2;   
                scale*=2;   
            }   
    
            BitmapFactory.Options o2 = new BitmapFactory.Options();   
            o2.inSampleSize=scale;   
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);   
        } catch (FileNotFoundException e) {}   
        return null;   
    }   
    
    /任务队列  
    private class PhotoToLoad   
    {   
        public String url;   
        public ImageView imageView;   
        public PhotoToLoad(String u, ImageView i){   
            url=u;   
            imageView=i;   
        }   
    }   
    
    class PhotosLoader implements Runnable {   
        PhotoToLoad photoToLoad;   
        PhotosLoader(PhotoToLoad photoToLoad){   
            this.photoToLoad=photoToLoad;   
        }   
    
        @Override  
        public void run() {   
            if(imageViewReused(photoToLoad))   
                return;   
            Bitmap bmp=getBitmap(photoToLoad.url);   
            memoryCache.put(photoToLoad.url, bmp);   
            if(imageViewReused(photoToLoad))   
                return;   
            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);   
            Activity a=(Activity)photoToLoad.imageView.getContext();   
            a.runOnUiThread(bd);   
        }   
    }   
    
    boolean imageViewReused(PhotoToLoad photoToLoad){   
        String tag=imageViews.get(photoToLoad.imageView);   
        if(tag==null || !tag.equals(photoToLoad.url))   
            return true;   
        return false;   
    }   
    
    //用于显示位图在UI线程  
    class BitmapDisplayer implements Runnable   
    {   
        Bitmap bitmap;   
        PhotoToLoad photoToLoad;   
        public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}   
        public void run()   
        {   
            if(imageViewReused(photoToLoad))   
                return;   
            if(bitmap!=null)   
                photoToLoad.imageView.setImageBitmap(bitmap);   
            else  
                photoToLoad.imageView.setImageResource(stub_id);   
        }   
    }   
    
    public void clearCache() {   
        memoryCache.clear();   
        fileCache.clear();   
    }   
    
}   

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class ImageLoader {

MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;

public ImageLoader(Context context){
fileCache=new FileCache(context);
executorService=Executors.newFixedThreadPool(5);
}

final int stub_id = R.drawable.no_image;
public void DisplayImage(String url, ImageView imageView)
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}

private void queuePhoto(String url, ImageView imageView)
{
PhotoToLoad p=new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}

private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);

//从sd卡
Bitmap b = decodeFile(f);
if(b!=null)
return b;

//从网络
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}

//解码图像用来减少内存消耗
private Bitmap decodeFile(File f){
try {
//解码图像大小
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);

//找到正确的刻度值,它应该是2的幂。
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}

BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

/任务队列
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}

class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad=photoToLoad;
}

@Override
public void run() {
if(imageViewReused(photoToLoad))
return;
Bitmap bmp=getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
if(imageViewReused(photoToLoad))
return;
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}

boolean imageViewReused(PhotoToLoad photoToLoad){
String tag=imageViews.get(photoToLoad.imageView);
if(tag==null || !tag.equals(photoToLoad.url))
return true;
return false;
}

//用于显示位图在UI线程
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
public void run()
{
if(imageViewReused(photoToLoad))
return;
if(bitmap!=null)
photoToLoad.imageView.setImageBitmap(bitmap);
else
photoToLoad.imageView.setImageResource(stub_id);
}
}

public void clearCache() {
memoryCache.clear();
fileCache.clear();
}

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

[java]
view plain
copy

print?

import java.io.IOException;   
import java.io.StringReader;   
import java.io.UnsupportedEncodingException;     
import javax.xml.parsers.DocumentBuilder;   
import javax.xml.parsers.DocumentBuilderFactory;   
import javax.xml.parsers.ParserConfigurationException;     
import org.apache.http.HttpEntity;   
import org.apache.http.HttpResponse;   
import org.apache.http.client.ClientProtocolException;   
import org.apache.http.client.methods.HttpPost;   
import org.apache.http.impl.client.DefaultHttpClient;   
import org.apache.http.util.EntityUtils;   
import org.w3c.dom.Document;   
import org.w3c.dom.Element;   
import org.w3c.dom.Node;   
import org.w3c.dom.NodeList;   
import org.xml.sax.InputSource;   
import org.xml.sax.SAXException;    
import android.util.Log;   
    
public class XMLParser {   
    
    // 构造方法  
    public XMLParser() {   
    
    }   
    
    /**  
     * 从URL获取XML使HTTP请求 
     * @param url string  
     * */  
    public String getXmlFromUrl(String url) {   
        String xml = null;   
    
        try {   
            // defaultHttpClient   
            DefaultHttpClient httpClient = new DefaultHttpClient();   
            HttpPost httpPost = new HttpPost(url);   
    
            HttpResponse httpResponse = httpClient.execute(httpPost);   
            HttpEntity httpEntity = httpResponse.getEntity();   
            xml = EntityUtils.toString(httpEntity);   
    
        } catch (UnsupportedEncodingException e) {   
            e.printStackTrace();   
        } catch (ClientProtocolException e) {   
            e.printStackTrace();   
        } catch (IOException e) {   
            e.printStackTrace();   
        }   
        return xml;   
    }   
    
    /**  
     * 获取XML DOM元素 
     * @param XML string  
     * */  
    public Document getDomElement(String xml){   
        Document doc = null;   
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();   
        try {   
    
            DocumentBuilder db = dbf.newDocumentBuilder();   
    
            InputSource is = new InputSource();   
                is.setCharacterStream(new StringReader(xml));   
                doc = db.parse(is);    
    
            } catch (ParserConfigurationException e) {   
                Log.e("Error: ", e.getMessage());   
                return null;   
            } catch (SAXException e) {   
                Log.e("Error: ", e.getMessage());   
                return null;   
            } catch (IOException e) {   
                Log.e("Error: ", e.getMessage());   
                return null;   
            }   
    
            return doc;   
    }   
    
    /** 获取节点值 
      * @param elem element  
      */  
     public final String getElementValue( Node elem ) {   
         Node child;   
         if( elem != null){   
             if (elem.hasChildNodes()){   
                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){   
                     if( child.getNodeType() == Node.TEXT_NODE  ){   
                         return child.getNodeValue();   
                     }   
                 }   
             }   
         }   
         return "";   
     }   
    
     /**  
      * 获取节点值 
      * @param Element node  
      * @param key string  
      * */  
     public String getValue(Element item, String str) {   
            NodeList n = item.getElementsByTagName(str);   
            return this.getElementValue(n.item(0));   
        }   
}  

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.util.Log;

public class XMLParser {

// 构造方法
public XMLParser() {

}

/**
* 从URL获取XML使HTTP请求
* @param url string
* */
public String getXmlFromUrl(String url) {
String xml = null;

try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);

HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);

} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xml;
}

/**
* 获取XML DOM元素
* @param XML string
* */
public Document getDomElement(String xml){
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {

DocumentBuilder db = dbf.newDocumentBuilder();

InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);

} catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}

return doc;
}

/** 获取节点值
* @param elem element
*/
public final String getElementValue( Node elem ) {
Node child;
if( elem != null){
if (elem.hasChildNodes()){
for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
if( child.getNodeType() == Node.TEXT_NODE  ){
return child.getNodeValue();
}
}
}
}
return "";
}

/**
* 获取节点值
* @param Element node
* @param key string
* */
public String getValue(Element item, String str) {
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(0));
}
}
       ④程序缓存的处理,主要是内存缓存+文件缓存。内存缓存中网上很多是采用SoftReference来防止堆溢出:

     MemoryCache.java:

[java]
view plain
copy

print?

import java.lang.ref.SoftReference;  
import java.util.Collections;  
import java.util.HashMap;  
import java.util.Map;  
import android.graphics.Bitmap;  
  
public class MemoryCache {  
    private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());//软引用  
      
    public Bitmap get(String id){  
        if(!cache.containsKey(id))  
            return null;  
        SoftReference<Bitmap> ref=cache.get(id);  
        return ref.get();  
    }  
      
    public void put(String id, Bitmap bitmap){  
        cache.put(id, new SoftReference<Bitmap>(bitmap));  
    }  
  
    public void clear() {  
        cache.clear();  
    }  
}  

import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import android.graphics.Bitmap;

public class MemoryCache {
private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());//软引用

public Bitmap get(String id){
if(!cache.containsKey(id))
return null;
SoftReference<Bitmap> ref=cache.get(id);
return ref.get();
}

public void put(String id, Bitmap bitmap){
cache.put(id, new SoftReference<Bitmap>(bitmap));
}

public void clear() {
cache.clear();
}
}
      FileCache.java

[java]
view plain
copy

print?

import java.io.File;  
import android.content.Context;  
  
public class FileCache {  
      
    private File cacheDir;  
      
    public FileCache(Context context){  
        //找一个用来缓存图片的路径  
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))  
            cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList");  
        else  
            cacheDir=context.getCacheDir();  
        if(!cacheDir.exists())  
            cacheDir.mkdirs();  
    }  
      
    public File getFile(String url){  
          
        String filename=String.valueOf(url.hashCode());  
        File f = new File(cacheDir, filename);  
        return f;  
          
    }  
      
    public void clear(){  
        File[] files=cacheDir.listFiles();  
        if(files==null)  
            return;  
        for(File f:files)  
            f.delete();  
    }  
  
}  

import java.io.File;
import android.content.Context;

public class FileCache {

private File cacheDir;

public FileCache(Context context){
//找一个用来缓存图片的路径
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}

public File getFile(String url){

String filename=String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
return f;

}

public void clear(){
File[] files=cacheDir.listFiles();
if(files==null)
return;
for(File f:files)
f.delete();
}

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

[java]
view plain
copy

print?

import java.io.InputStream;  
import java.io.OutputStream;  
  
  
public class Utils {  
    public static void CopyStream(InputStream is, OutputStream os)  
    {  
        final int buffer_size=1024;  
        try  
        {  
            byte[] bytes=new byte[buffer_size];  
            for(;;)  
            {  
              int count=is.read(bytes, 0, buffer_size);  
              if(count==-1)  
                  break;  
              os.write(bytes, 0, count);  
              is.close();  
              os.close();  
            }  
        }  
        catch(Exception ex){}  
    }  
}  

import java.io.InputStream;
import java.io.OutputStream;

public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {
            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;
              os.write(bytes, 0, count);
              is.close();
              os.close();
            }
        }
        catch(Exception ex){}
    }
}


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

[java]
view plain
copy

print?

public static byte[] readStream(InputStream inStream) throws Exception{  
  
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
byte[] buffer = new byte[1024];  
int len = -1;  
while( (len=inStream.read(buffer)) != -1){  
outSteam.write(buffer, 0, len);  
  
}  
outSteam.close();  
inStream.close();  
return outSteam.toByteArray();  
  
}  
}  

public static byte[] readStream(InputStream inStream) throws Exception{

ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while( (len=inStream.read(buffer)) != -1){
outSteam.write(buffer, 0, len);

}
outSteam.close();
inStream.close();
return outSteam.toByteArray();

}
}
      最后就是主Activity的代码了,

[java]
view plain
copy

print?

package com.example.androidhive;  
  
import java.util.ArrayList;  
import java.util.HashMap;  
import org.w3c.dom.Document;  
import org.w3c.dom.Element;  
import org.w3c.dom.NodeList;  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.AdapterView;  
import android.widget.AdapterView.OnItemClickListener;  
import android.widget.ListView;  
  
public class CustomizedListView extends Activity {  
    // 所有的静态变量  
    static final String URL = "http://api.androidhive.info/music/music.xml";//xml目的地址,打开地址看一下  
    // XML 节点  
    static final String KEY_SONG = "song"; // parent node  
    static final String KEY_ID = "id";  
    static final String KEY_TITLE = "title";  
    static final String KEY_ARTIST = "artist";  
    static final String KEY_DURATION = "duration";  
    static final String KEY_THUMB_URL = "thumb_url";  
      
    ListView list;  
        LazyAdapter adapter;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
  
        ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();  
  
        XMLParser parser = new XMLParser();  
        String xml = parser.getXmlFromUrl(URL); // 从网络获取xml  
        Document doc = parser.getDomElement(xml); // 获取 DOM 节点  
          
        NodeList nl = doc.getElementsByTagName(KEY_SONG);  
        // 循环遍历所有的歌节点 <song>  
        for (int i = 0; i < nl.getLength(); i++) {  
            // 新建一个 HashMap  
            HashMap<String, String> map = new HashMap<String, String>();  
            Element e = (Element) nl.item(i);  
            //每个子节点添加到HashMap关键= >值  
            map.put(KEY_ID, parser.getValue(e, KEY_ID));  
            map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));  
            map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));  
            map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));  
            map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));  
  
            // HashList添加到数组列表  
            songsList.add(map);  
        }  
          
  
        list=(ListView)findViewById(R.id.list);  
          
          
              adapter=new LazyAdapter(this, songsList);          
              list.setAdapter(adapter);  
          
  
        //为单一列表行添加单击事件  
  
        list.setOnItemClickListener(new OnItemClickListener() {  
  
            @Override  
            public void onItemClick(AdapterView<?> parent, View view,  
                    int position, long id) {  
                              
                        //这里可以自由发挥,比如播放一首歌曲等等  
            }  
        });       
    }     
}  

package com.example.androidhive;

import java.util.ArrayList;
import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

public class CustomizedListView extends Activity {
// 所有的静态变量
static final String URL = "http://api.androidhive.info/music/music.xml";//xml目的地址,打开地址看一下
// XML 节点
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";

ListView list;
LazyAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();

XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // 从网络获取xml
Document doc = parser.getDomElement(xml); // 获取 DOM 节点

NodeList nl = doc.getElementsByTagName(KEY_SONG);
// 循环遍历所有的歌节点 <song>
for (int i = 0; i < nl.getLength(); i++) {
// 新建一个 HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
//每个子节点添加到HashMap关键= >值
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));

// HashList添加到数组列表
songsList.add(map);
}

list=(ListView)findViewById(R.id.list);

adapter=new LazyAdapter(this, songsList);
list.setAdapter(adapter);

//为单一列表行添加单击事件

list.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {

//这里可以自由发挥,比如播放一首歌曲等等
}
});
}
}
      最后看一下效果:

                                                        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: