文档章节

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

会飞柚子
 会飞柚子
发布于 2016/02/24 12:35
字数 789
阅读 121
收藏 13

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

三级缓存分别是:

  1. 软引用SoftReference,cache在内存中

  2. 文件缓存在本地SDcard文件夹中,遇到文件名相同的图片则从本地取,且加入软引用中

  3. 从网络下载,并保存在本地,且加入软引用中

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

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

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

代码如下:

/**
 * 异步根据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);

}
}

关于异步加载图片,下面的几篇博客可供参考: http://www.iteye.com/topic/1118828http://blog.csdn.net/geniusxiaoyu/article/details/7470163http://blog.csdn.net/zshshuai/article/details/7798086 http://www.2cto.com/kf/201403/283382.html

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

本文转载自:http://www.thinksaas.cn/group/topic/347385/

会飞柚子
粉丝 0
博文 34
码字总数 3972
作品 0
深圳
程序员
私信 提问
Android面试题知识点积累(二)

一个Bitmap占用内存计算 即是通过占用的像素点多少和一个像素点占的字节数。一个像素用一串二进制表示。 即是宽高byte数。Bitmap.Config有一个属性决定这个字节数。分别为: 一个int值32位,...

奔跑吧焦宇
03/26
0
0
Android 性能优化:手把手教你优化Bitmap图片资源的使用

前言 在 开发中,性能优化策略十分重要 本文主要讲解性能优化中的Bitmap 使用优化,希望你们会喜欢 目录 1. 优化原因 即 为什么要优化图片资源,具体如下图:

Carson_Ho
2018/04/24
0
0
Android异步下载图片并且缓存图片到本地

在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML资源,其中包括图片,我们要做的解析XML里面的数...

liuher
2014/07/23
0
0
Android 2019最新面试实战总结

Android: 今日头条屏幕适配的原理? 1:首先计算出 density,计算公式:当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = densitydensity 的意思就是 1 dp 占当前设备多少像素...

终端研发部
03/28
0
0
Android实战——RxJava2解锁图片三级缓存框架

RxJava2解锁图片三级缓存框架 本篇文章包括以下内容 前言 图片三级缓存的介绍 框架结构目录的介绍 构建项目整体框架 实现图片三级缓存 演示效果 源码下载 结语 前言 RxJava2作为如今那么主流...

qq_30379689
2017/04/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Oracle SQL语法实例合集

如需转载请注明出处https://my.oschina.net/feistel/blog/3052024 目的:迅速激活Oracle SQL 参考:《Oracle从入门到精通》 ------------------------------------------------------------......

LoSingSang
57分钟前
1
0
增加 PostgreSQL 服务进程的最大打开文件数

https://serverfault.com/questions/628610/increasing-nproc-for-processes-launched-by-systemd-on-centos-7 要在systemd的配置里加才行...

helloclia
今天
2
0
组合模式在商品分类列表中的应用

在所有的树形结构中最适合的设计模式就是组合模式,我们看看常用商品分类中如何使用。 先定义一个树形结构的商品接口 public interface TreeProduct { List<TreeProduct> allProducts(...

算法之名
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部