软引用,需要通过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);
}