android异步图片加载三之handler+线程池+消息队列模式+缓存

假象现在有这样一个需求:

一个微博客户端或者多媒体客户端需要从服务端拉取一些数据,该数据中包含了很多图片,如果不用异步加载方式,可能会使主线程阻塞导致ANR异常,但是异步加载后如果每次都通过网络去下载图片,性能上会差很多,而且也会浪费流量,导致用户的不满,故现在增加一个缓存用来存储图片,缓存中包含内存存储和sdcard存储。先从缓存中去,在缓存中先从内存中取出,如果内存中没有再从sdcard去,如果sdcard中存在则直接返回该图片资源并放入内存中,如果两者都没有则从网络上下载,下载后并放入sdcard中供下次使用,这样就节约了资源开销,下面是主要代码:

PicManager(用来处理图片的操作):

public class PicManager {

	private Map<String,SoftReference<Bitmap>> imgCache ;
	private Context ctx;
	
	public PicManager(Map<String,SoftReference<Bitmap>> imgCache,Context ctx) {
		this.ctx = ctx;
		this.imgCache = imgCache;
	}
	
	
	/**
	 * 从网络上下载
	 * @param url
	 * @return
	 */
	public Bitmap getBitMapFromUrl(String url) {
		Bitmap bitmap = null;
		URL u =null;
		HttpURLConnection conn = null;
		InputStream is = null;
		try {
			u = new URL(url);
			conn = (HttpURLConnection)u.openConnection();
			is = conn.getInputStream();
			bitmap = BitmapFactory.decodeStream(is);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bitmap;
	}
	
	/**
	 * 从文件中读取
	 * @return
	 * @throws Exception 
	 */
	private Bitmap getBitMapFromSDCard(String url) throws Exception {
		Bitmap bitmap = null;
		String filename = MD5Util.getMD5(url);
		FileInputStream fis = ctx.openFileInput(filename);
		bitmap = BitmapFactory.decodeStream(fis);
		return bitmap;
	}
	
	/**
	 * 从缓存中读取
	 * @param url
	 * @return
	 * @throws Exception 
	 */
	public Bitmap getImgFromCache(String url) throws Exception {
		Bitmap bitmap = null;
		//从内存中读取
		if(imgCache.containsKey(url)) {
			synchronized (imgCache) {
				SoftReference<Bitmap> bitmapReference = imgCache.get(url);
				if(null != bitmapReference) {
					bitmap = bitmapReference.get();
				}
			}
		} else {//否则从文件中读取
			bitmap = getBitMapFromSDCard(url);
			//将图片保存进内存中
			imgCache.put(url, new SoftReference<Bitmap>(bitmap));
		}
		return bitmap;
	}
	
	/**
	 * 将图片写入sdcard中
	 * @param bitmap
	 * @param url
	 * @throws Exception
	 */
	public void writePic2SDCard(Bitmap bitmap,String url) throws Exception {
		String filename = MD5Util.getMD5(url);
		FileOutputStream fos = ctx.openFileOutput(filename, ctx.MODE_APPEND);
		byte[] bitmapByte = PictureUtil.bitmap2Byte(bitmap);
		ByteArrayInputStream bis = new ByteArrayInputStream(bitmapByte);
		int len = 0;
		byte[] b = new byte[bis.available()];
		while((len = bis.read(b)) != -1) {
			fos.write(b, 0, len);
		}
		if(null != bis) {
			bis.close();
		}
		if(null != fos) {
			fos.close();
		}
	}
}


ImgLoader(用来加载图片):

public class ImgLoader {

	private Map<String,SoftReference<Bitmap>> imgCache = new HashMap<String,SoftReference<Bitmap>>();
	private Context ctx;
	
	public ImgLoader(Context ctx) {
		this.ctx = ctx;
	}
	
	private PicManager manager = new PicManager(imgCache,ctx);
	private Handler handler = new Handler();
	
	
	private ExecutorService threadPool = Executors.newFixedThreadPool(5);
	
	public Bitmap loadImg(final String url,final ImgCallback callback) {
		
		//先从缓存中读取图片资源
		Bitmap bitmap = null;
		try {
			bitmap = manager.getImgFromCache(url);;
			
			if(null == bitmap) {
				//开启线程从网络上下载
				threadPool.submit(new Runnable() {//submit方法确保下载是从线程池中的线程执行
					@Override
					public void run() {
						final Bitmap bitmapFromUrl = manager.getBitMapFromUrl(url);
						try {
							manager.writePic2SDCard(bitmapFromUrl,url);
						} catch (Exception e) {
							e.printStackTrace();
						}
						handler.post(new Runnable() {
							@Override
							public void run() {
								callback.refresh(bitmapFromUrl);
							}
						});
					}
				});
			} else {
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bitmap;
	}
	
}


ImgCallback callback是一个接口,用来刷新界面:

public interface ImgCallback {

	
	public void refresh(Bitmap bitmap);
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值