android中用弱引用管理bitmap

软引用,需要通过SoftReference类来实现,当一个对象只有一个软引用,它有可能被垃圾回收机制回收。内存空间足够时,不会被回收,不足够时将被回收 

弱引用,需要通过WeakReference类来实现,当垃圾回收机制运行时,不管内存是否足够,总会回收该对象所占用的内存


众所周知,使用bitmap时容易引起oom,虽然我们可以在bitmap不适用的时候通过recycle方法释放bitmap占用的内存,但是如果这个方法调用的时间点不合理,很容易引起 use a recycle bitmap的异常。

对此,可以使用弱引用来管理bitmap。将所有用到的bitmap对象放到一个hashmap中,用弱引用来保存,如果再用到这个bitmap的时候,根据相应的key直接取出来,相当于一个高速缓存池。如果确定不再使用的时候手动将其recycle,保证这个程序不会重复创建过多的bitmap对象。此外弱引用对象可以在系统内存不足的时候自动被系统回收。


以下是小弟写的一个弱引用管理bitmap的工具类代码,仅供学习参考


public class ImageUtils {
	/**保存图片的集合,key为图片的url*/
	public static Map<String,WeakReference<Drawable>> imageCache = new HashMap<String, WeakReference<Drawable>>();
	
	private static MyHandler myHandler = new MyHandler(Looper.getMainLooper());
	
	public static void sendMessage(IFBackListener backlistener,Object exInfo){
		Message m = Message.obtain();
		m.what = 0;
		m.obj = new Object[]{backlistener,exInfo};
		myHandler.sendMessage(m);
	}
	
	private static class MyHandler extends Handler{
		MyHandler(Looper looper){
			super(looper);
		}
		public void handleMessage(Message m) {//处理消息
			Object[] pars = (Object[])m.obj;
			if(pars[0] instanceof IFBackListener){
				((IFBackListener)pars[0]).processBack(pars[1]);
			}
		}
	}
	
	/**
	 * 根据url获取图片,如果缓存中没有这个图片,会返回宽高并异步加载图片
	 * Description:
	 * @param callBack	回调
	 * @param url	图片url
	 * @param needAsync	是否需要异步加载
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-24 下午12:09:21
	 */
	public static Object newImage(IFBackListener callBack, String url, boolean needAsync) {
		if(url == null || url.equals("")) {
			return null;
		}
		if(needAsync) {//需要异步加载
			return newImageByAsync(callBack, url);
		} else {//不需要异步加载
			Drawable drawable = (Drawable) getImageFromCache(url);
			if(drawable != null) {//缓存中有这个图片
				return drawable;
			} else {
				drawable = newDrawable(url);
				return drawable;
			} 
		}
	}
	
	/**
	 * 根据url获取一个Drawable
	 * Description:
	 * @param url
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-31 上午10:43:58
	 */
	public static Drawable newDrawable(String url) {
		if(url == null || url.equals("")) {
			return null;
		}
		Drawable drawable = null;
		drawable = new BitmapDrawable(url);
		if(drawable != null) {
			//将图片加入缓存
			ImageUtils.imageCache.put(url, new WeakReference<Drawable>(drawable));
		}
		return drawable;
	}
	
	/**
	 * 根据url获取图片,如果缓存中没有这个图片,会返回宽高并异步加载图片
	 * Description:
	 * @param callBack	回调
	 * @param url	图片url
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-24 下午12:09:21
	 */
	public static Object newImageByAsync(IFBackListener callBack, String url) {
		if(url == null || url.equals("")) {
			return null;
		}
		Drawable d = (Drawable) getImageFromCache(url);
		if(d != null) {//缓存中有这个图片
			return d;
		} else {//缓存中没有这个图片,那么获取图片的宽高
			int[] options = null;
			options = getImageBounds(url);
			if(options != null && options[0] > 0 && options[1] >0) {//存在正常的宽高
				if(callBack != null) {//回调
					callBack.processBack(options);
				}
				//发送消息,异步加载图片
				sendMessage(callBack, url);
				return null;
			}
		} 
		return null;
	}
	
	/**
	 * 到集合缓存中查找图片,有则返回Drawable对象,没有返回空
	 * Description:
	 * @param url
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-24 上午10:34:33
	 */
	public static Object getImageFromCache(String url) {
		if(url == null || url.equals("")) {
			return null;
		}
		if(hasImage(url)) {//缓存中有这个图片
			Drawable d = getDrawableFromCache(url);
			if(d != null) {
				return d;
			}
		}
		return null;
	}
	
	/**
	 * 图片是否存在
	 * Description:
	 * @param url
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-24 上午10:07:15
	 */
	public static boolean hasImage(String url) {
		return imageCache.containsKey(url);
	}
	
	/**
	 * 获取指定url的图片的宽高
	 * Description:
	 * @param url
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-23 下午05:24:34
	 */
	private static int[] getImageBounds(String url) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true; //只获取宽高
	    BitmapFactory.decodeFile(url, options);//这里返回的bitmap应为null
	    return new int[]{options.outWidth,options.outHeight};
	}
	
	/**
	 * 根据key到缓存集合中获取Drawable
	 * Description:
	 * @param key
	 * @return
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-23 下午05:23:59
	 */
	private static Drawable getDrawableFromCache(String key) {
		if(hasImage(key)) {//缓存中有这个图片
			WeakReference<Drawable> ref = imageCache.get(key);
			Drawable d = ref.get();
			if (d != null) {
				return d;
			}
		}
		return null;
	}
	
	/**
	 * 回收指定图片
	 * Description:
	 * @param url	图片的url,根据这个url到集合缓存中找图片
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-23 下午05:51:45
	 */
	public static void recycleImage(String url) {
		if(url == null || url.equals("")) {
			return;
		}
		Drawable d = getDrawableFromCache(url);
		if(d != null) {
			Bitmap b = ((BitmapDrawable)d).getBitmap();
			if(b != null && !b.isRecycled()){
			    b.recycle();
			}
			b = null;
			d = null;
		}
	}
	
	/**
	 * 清空集合中所有缓存
	 * Description:
	 *<br/> ModifiedLog:
	 *<br/> Log ID: 1.0 (Log编号 依次递增)
	 * <br/>Modified By: liubin Email:liubin@d-heaven.com at 2012-8-23 下午05:36:07
	 */
	public static void clearImageCache() {
		if(imageCache == null ||imageCache.isEmpty()) {
			return;
		}
		//遍历集合,找出所有Drawable,将其中bitmap回收并置空
		for(Map.Entry<String,WeakReference<Drawable>> entry:imageCache.entrySet()){
			Drawable d = entry.getValue().get();
			if(d != null) {
				Bitmap b = ((BitmapDrawable)d).getBitmap();
				if(b != null && !b.isRecycled()){
				    b.recycle();
				}
				b = null;
				d = null;
			}
		}
		imageCache.clear();
	}
}

interface IFBackListener {
	Object processBack(Object targetO);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值