您的位置:首页 > 移动开发 > Android开发

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

2016-06-29 23:09 423 查看

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

三级缓存分别是:

软引用SoftReference,cache在内存中
文件缓存在本地SDcard文件夹中,遇到文件名相同的图片则从本地取,且加入软引用中
从网络下载,并保存在本地,且加入软引用中
其中缓存的文件,其文件名经过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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: