`
dyingbleed
  • 浏览: 116490 次
  • 性别: Icon_minigender_1
  • 来自: 东莞
社区版块
存档分类
最新评论

【Android】ListView异步加载远端图片

阅读更多

LoadRemoteImage

公有成员方法setRemoteImageListener用于监听远端图片

传入两个参数:String url 图片URL地址  OnRemoteImageListener listener OnRemoteImageListener接口

 

线程Runnable接口处理流程图:

 

 

 

package lizhen.dg;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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.apache.http.util.EntityUtils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

/**
 * 遠端圖片類
 * */
public class LoadRemoteImage {

	private ExecutorService pool; //線程池
	
	private final int MESSAGE_OK = 1; //遠端圖片獲取成功消息
	private final int MESSAGE_ERROR = -1; //遠端圖片獲取錯誤消息
	
	private ImageBuffer imageBuffer; //圖片緩存
	
	
	/**
	 * 構造函數
	 * 執行初始化操作
	 * */
	public LoadRemoteImage() {
		pool = Executors.newCachedThreadPool();
		imageBuffer = new ImageBuffer();
	}
	
	/**
	 * 設置遠端圖片事件監聽器
	 * @param url 圖像URL地址
	 * @param listener 遠端圖片監聽器
	 * */
	public void setRemoteImageListener(final String url, final OnRemoteImageListener listener) {
		
		/*
		 * 遠端圖片消息處理Handler
		 * */
		final Handler handler = new Handler() {

			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				int what = msg.what;
				switch(what) {
				case MESSAGE_OK : //成功 
					listener.onRemoteImage((Bitmap) msg.obj); //調用onRemoteImage回調方法
					break;
				case MESSAGE_ERROR : //錯誤
					listener.onError((String) msg.obj); ////調用onError回調方法
					break;
				}
			}
			
		};
		
		/*
		 * 向線程池中添加新任務
		 * 下載給定URL地址圖片
		 * */
		pool.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					Bitmap image = null;
					/*
					 * 如果圖片緩存中沒有該圖片,則下載放入緩存中
					 * */
					if((image = imageBuffer.get(url)) == null) {
						byte[] resource = httpRequestByteArray(url); //HTTP請求圖片字節數據
						image = optimizeBitmap(resource, 100, 100); //獲得優化的圖像
						imageBuffer.put(url, image);
					}
					handler.sendMessage(handler.obtainMessage(MESSAGE_OK, image)); //遠端圖像下載成功
				} catch (Exception e) {
					/*
					 * 異常處理
					 * */
					handler.sendMessage(handler.obtainMessage(MESSAGE_ERROR, e.getMessage()));
					return;
				}
			}
		});
	}
	
	/** 
     * 使用HTTP GET方式請求 
     * @param url URL地址 
     * @return HttpEntiry對象 
	 * @throws Exception 
     * */  
    private byte[] httpRequestByteArray(String url) throws Exception {  
        byte[] result = null;  
        HttpGet httpGet = new HttpGet(url);  
        HttpClient httpClient = new DefaultHttpClient();  
        HttpResponse httpResponse;  
        httpResponse = httpClient.execute(httpGet);  
        int httpStatusCode = httpResponse.getStatusLine().getStatusCode();  
        /* 
         * 判斷HTTP狀態碼是否為200 
         * */  
        if(httpStatusCode == HttpStatus.SC_OK) {  
            result = EntityUtils.toByteArray(httpResponse.getEntity());  
        } else {
        	throw new Exception("HTTP: "+httpStatusCode);
        }
        return result;  
    }
	
    private Bitmap optimizeBitmap(byte[] resource, int maxWidth, int maxHeight) {  
        Bitmap result = null;  
        int length = resource.length;  
        BitmapFactory.Options options = new BitmapFactory.Options();      
        options.inJustDecodeBounds = true;  
        result = BitmapFactory.decodeByteArray(resource, 0, length, options);  
        int widthRatio = (int) Math.ceil(options.outWidth / maxWidth);  
        int heightRatio = (int) Math.ceil(options.outHeight / maxHeight);  
        if(widthRatio > 1 || heightRatio > 1) {  
            if(widthRatio > heightRatio) {  
                options.inSampleSize = widthRatio;  
            } else {  
                options.inSampleSize = heightRatio;  
            }  
        }  
        options.inJustDecodeBounds = false;  
        result = BitmapFactory.decodeByteArray(resource, 0, length, options);  
        return result;  
    }
    
    /**
     * 遠端圖片監聽器
     * */
	public interface OnRemoteImageListener {
		
		/**
		 * 遠端圖片處理
		 * @param image 位圖圖片
		 * */
		void onRemoteImage(Bitmap image);
		
		/**
		 * 錯誤處理
		 * @param error 錯誤信息
		 * */
		void onError(String error);
		
	}
	
}

 

ImageBuffer 图片缓存

String键->SoftReference<Bitmap>值储存缓存图片

SoftReference软引用

在内存吃紧抛出“OutOfMemory”异常之前,会被JVM回收,此时调用get方法会返回null

 

 

package lizhen.dg;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;

/**
 * 圖片緩存類
 * */
public class ImageBuffer {
	
	private Map<String, SoftReference<Bitmap>> buffer = new HashMap<String, SoftReference<Bitmap>>(); //圖片緩存

	/**
	 * 將圖片放進緩存中
	 * @param key 鍵值
	 * @param image Bitmap位圖
	 * */
	public void put(String key, Bitmap image) {
		SoftReference<Bitmap> reference = new SoftReference<Bitmap>(image);
		synchronized(buffer) {
			buffer.put(key, reference);
		}
	}

	/**
	 * 從緩存中取得圖片
	 * @param key 鍵值
	 * @return Bitmap位圖
	 * */
	public Bitmap get(String key) {
		Bitmap result = null;
		synchronized(buffer) {
			if(buffer.containsKey(key)) {
				result = buffer.get(key).get();
			}
		}
		return result;
	}

}

 

ListActivity

ListView列表异步加载远端图片

 

package lizhen.dg;

import android.app.ListActivity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.Toast;

public class Main extends ListActivity {
	
	private String data[] = {
			"http://192.168.211.86/pic/0.jpg"
			, "http://192.168.211.86/pic/1.jpg"
			, "http://192.168.211.86/pic/2.jpg"
			, "http://192.168.211.86/pic/3.jpg"
			, "http://192.168.211.86/pic/4.jpg"
			, "http://192.168.211.86/pic/5.jpg"
			, "http://192.168.211.86/pic/6.jpg"
			, "http://192.168.211.86/pic/7.jpg"
			, "http://192.168.211.86/pic/8.jpg"
			, "http://192.168.211.86/pic/9.jpg"
			, "http://192.168.211.86/pic/10.jpg"
			, "http://192.168.211.86/pic/11.jpg"
			, "http://192.168.211.86/pic/12.jpg" //錯誤的圖片地址
			};
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        setListAdapter(new MyListAdapter(this, data));
    }
    
    private class MyListAdapter extends BaseAdapter {
    	
    	private Context context;
    	private String[] data;
    	private LoadRemoteImage remoteImage;
    	
    	public MyListAdapter(Context context, String[] data) {
    		this.context = context;
    		this.data = data;
    		remoteImage = new LoadRemoteImage();
    	}

		@Override
		public int getCount() {
			return data.length;
		}

		@Override
		public Object getItem(int position) {
			return data[position];
		}

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

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			Holder holder = null;  
            if(convertView == null) {  
                convertView = getLayoutInflater().inflate(R.layout.item, parent, false);  
                holder = new Holder(convertView);  
                convertView.setTag(holder);  
            } else {  
                holder = (Holder) convertView.getTag();  
            }
            final ImageView icon = holder.getIcon();
            icon.setImageResource(R.drawable.icon);
            remoteImage.setRemoteImageListener((String) getItem(position), new LoadRemoteImage.OnRemoteImageListener() {
				
				@Override
				public void onError(String error) {
					Toast.makeText(context, error, Toast.LENGTH_LONG).show();
				}

				@Override
				public void onRemoteImage(Bitmap image) {
					icon.setImageBitmap(image);
				}
			});
            holder.getName().setText((String) getItem(position));  
            return convertView;  
		}
    	
    }
    
}

 

package lizhen.dg;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class Holder {
	private View parentView;  
    private ImageView iconImageView;  
    private TextView labelTextView;  
      
    public Holder(View view) {  
        this.parentView = view;  
    }  
      
    public ImageView getIcon() {  
        if(iconImageView == null) {  
            iconImageView = (ImageView) parentView.findViewById(R.id.item_IconImageView);  
        }  
        return iconImageView;  
    }  
      
    public TextView getName() {  
        if(labelTextView == null) {  
            labelTextView = (TextView) parentView.findViewById(R.id.item_NameTextView);  
        }  
        return labelTextView;  
    }  
}
 

运行结果:

 

  • 大小: 28.2 KB
  • 大小: 90.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics