Android 图片三级缓存机制工具类封装

Android 图片三级缓存机制工具类封装

三级缓存分别是:

  1. 软引用SoftReference,cache在内存中
  2. 文件缓存在本地SDcard文件夹中,遇到文件名相同的图片则从本地取,且加入软引用中
  3. 从网络下载,并保存在本地,且加入软引用中

其中缓存的文件,其文件名经过MD5转换,去掉了文件路径中的斜杠,目前该方法全存储成png格式的,也可进一步优化。注意需要静态初始化软引用,可保证全局有效。

实现的方法是通过集成一个AsyncTask,并定制里面的内容。好像也没什么特别好说的...

在做listview列表的时候,可把这一个task加入viewholder里,这样就能保证每个控件的唯一性了,比起封装一个AsyncImageView,要更简洁一些,并且能满足使用的要求

代码如下:


<span style="font-size:18px;">/**
 * 异步根据URL获取图片
 * 修改加入本地缓存和软引用
 * @author Jackland_zgl
*
*/
@SuppressLint("NewApi")
public class LoadingImgTask extends AsyncTask<Void, Void, Bitmap> {

 public static final String URL_KEY ="url";
 public static final String BITMAP_KEY ="bitmap";

 public static final String ImageCacheFilePath ="/sdcard/xiaomai/ImageCache/";
 private String url;
 private static HashMap<String, SoftReference<Bitmap>> cache; 
 RefreshDelegate refreshDelegate;

 /** 静态初始化软引用 */
 static { 
 cache = new HashMap<String, SoftReference<Bitmap>>(); 
}


 public LoadingImgTask(String url,RefreshDelegate rd) {
 this.url = url;
 this.refreshDelegate = rd;
}

@Override
 protected Bitmap doInBackground(Void... params) {

 Bitmap bm;
//1从软引用中取
 bm = getBitmapFromCache(url);
 if (bm!=null) {
// Log.d("image","缓存");
 return bm;
}

//2从本地中取
 bm = getBitmapFromLocal(ImageCacheFilePath , modifyUriToFileName(url));
 if (bm!=null) {
//放入缓存
 cache.put(url, new SoftReference<Bitmap>(bm));
// Log.d("image","本地");
 return bm;
}

 //3从网络取 ,若能取出则缓存
 bm = loadImageFromNet(url);
 if (bm!=null){
 try {
saveImageToSD(ImageCacheFilePath+modifyUriToFileName(url),bm);
 } catch (IOException e) {
 // TODO Auto-generated catch block
e.printStackTrace();
}
 cache.put(url, new SoftReference<Bitmap>(bm));
// Log.d("image","网络");
}
 return bm;
}

@Override
 protected void onPostExecute(Bitmap result) {
 HashMap<String,Object> map = new HashMap<String,Object>();
 map.put(RefreshDelegate.KEY_URL, url);
 map.put(RefreshDelegate.KEY_BITMAP, result);
 if (refreshDelegate!=null)
refreshDelegate.refresh(map);
}

/**
 * 从缓存中获取图片
 * @param url
*/
 public Bitmap getBitmapFromCache(String url) { 
 Bitmap bitmap = null;
 if (cache.containsKey(url)) { 
 bitmap = cache.get(url).get(); 
}
 return bitmap; 
}

/**
 * 从本地获取
 * @param path
 * @param url
 * @return
*/
 public Bitmap getBitmapFromLocal(String path,String url){
 return BitmapFactory.decodeFile(path+url);

}

/**
 * 从网络读取
 * @param url
 * @return
*/
 public static Bitmap loadImageFromNet(String url) {
 URL m;
 InputStream i = null;
 if (url == null) {
 return null;
}
 try {
 m = new URL(url);

 i = (InputStream) m.getContent();
 } catch (MalformedURLException e1) {
e1.printStackTrace();
 } catch (IOException e) {
e.printStackTrace();
 } catch (Exception e2) {
e2.printStackTrace();
}
 if (i == null) {
 return null;
}
 return BitmapFactory.decodeStream(i);
}

/**
 * 写图片文件到SD卡
*
 * @throws IOException
*/
 public static void saveImageToSD(String filePath,
 Bitmap bitmap) throws IOException {
Log.d("image","存在本地:"+filePath);
 if (bitmap != null) {
 File file = new File(filePath.substring(0,
filePath.lastIndexOf(File.separator)));
 if (!file.exists()) {
file.mkdirs();
}
 FileOutputStream fos = new FileOutputStream(filePath);
 ByteArrayOutputStream stream = new ByteArrayOutputStream();
 bitmap.compress(CompressFormat.PNG, 100, stream);

fos.write(stream.toByteArray());
fos.close();
}
}

/**
 * 修改URL里的斜杠
 * @param Url
 * @return
*/
 public static String modifyUriToFileName(String Url){
// String mUrl = Url.replaceAll("/","_").replaceAll("\.","-").replaceAll(":","_")+".jpg";
 String mUrl = MD5Util.md5(Url)+".png";
 return mUrl;
}


/**
 * 刷新代理
 * @author Jackland_zgl
*
*/
 public interface RefreshDelegate{
 public static String KEY_URL="url";
 public static String KEY_BITMAP="bitmap";

 public int refresh(HashMap<String,Object> result);

}
}

</span>
<span style="font-size:18px;">关于异步加载图片,下面的几篇博客可供参考: http://www.iteye.com/topic/1118828 http://blog.csdn.net/geniusxiaoyu/article/details/7470163 http://blog.csdn.net/zshshuai/article/details/7798086 http://www.2cto.com/kf/201403/283382.html

以上几篇代码没有提到LRU的实现,使用LRU可以真正的吸取内存空间做缓存,但是目前我实现的代码不怎么有效,在此处mark一下,调成功之后再更新这个封装类</span>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值