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

来源:互联网 发布:有道云笔记 ubuntu版 编辑:程序博客网 时间:2024/05/22 12:24

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/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一下,调成功之后再更新这个封装类


文章为原创,转载请注明出处。

0 0