资讯专栏INFORMATION COLUMN

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

Ajian / 686人阅读

摘要:注意需要静态初始化软引用,可保证全局有效。实现的方法是通过集成一个,并定制里面的内容。

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

三级缓存分别是:

软引用SoftReference,cache在内存中

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

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

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

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

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

代码如下:

/**
 * 异步根据URL获取图片
 * 修改加入本地缓存和软引用
 * @author Jackland_zgl
 *
 */
@SuppressLint("NewApi")
public class LoadingImgTask extends AsyncTask {

    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> cache; 
    RefreshDelegate  refreshDelegate;

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


    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(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(bm));
//          Log.d("image","网络");
        }
        return bm;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        HashMap map = new HashMap();
        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 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一下,调成功之后再更新这个封装类


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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12165.html

相关文章

  • 图片处理工具

    摘要:但是我们还是发现至少有两个问题,以为例,第一,当需求变动,你最全面详解图像处理的最重要类之一。将图片存储到一个特殊的区域,避免了。 Android7.0 完美适配——FileProvider 拍照裁剪全解析 适配 android7.0 中的拍照相册裁剪功能 使用 photoView 实现可点击放大到全屏显示的控件,效果类似于微信朋友圈点开看大图 使用 photoView 实现可点击放大...

    wangxinarhat 评论0 收藏0
  • 图片处理工具 - 收藏集 - 掘金

    摘要:图片预览工具掘金仿微信的图片预览工具这是一个仿朋友圈的列表。加载图片工具使处理发送大图掘金什么是就是内存溢出,即。图片加载框架最详细的使用指南掘金写在前面中有几个比较有名的图片加载框架,和。 Android 图片预览工具 - Android - 掘金仿微信的图片预览工具 01.png 这是一个仿朋友圈的列表。 加载图片工具使... 处理 Android 发送大图 OOM - Andro...

    AbnerMing 评论0 收藏0
  • Android图片三级缓存

    摘要:为什么要使用三级缓存如今的经常会需要网络交互,通过网络获取图片是再正常不过的事了假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用...

    jerry 评论0 收藏0
  • 库 - 收藏集 - 掘金

    摘要:历时一年,官方已经新增章节,我们再次发力,于下雨,飘雪,红包雨,碰撞球,自定义掘金效果展示有没有兴趣继续看下去,直接看下颜值是第一步了。 【福利】成为专业程序员路上用到的各种优秀资料、神器及框架 - 工具资源 - 掘金本文是鄙人工作这几年随手收集整理的一些自认为还不错的资料,成长的道理上需要积累,这么长时间了,是时候放出来分享下了,或许能帮助到你。 欢迎点赞,让更多人看到,让福利普照。...

    qc1iu 评论0 收藏0
  • Android 2019最新面试实战总结

    摘要:内存泄漏当应用内部不再需要某个实例后,但是这个对象却仍然被引用,这个情况就叫做内存泄露。安卓虚拟机为每一个应用分配一定的内存空间,当内存泄露到达一定的程度就会造成内存溢出。点击登录跳转页面中所有操作都与用户密切相关,是 Android: 今日头条屏幕适配的原理? 1:首先计算出 density,计算公式:当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = densit...

    whataa 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<