图片三级缓存策略

我们在现实一个图片的时候,按照顺序来是从内存中查找是否有图片缓存,有,直接读取,无,就查找本地文件,有,直接读取,无,通过网络获取。
按照这个步骤一个一个来建立相应的类:

内存缓存

public class MemoryCacheUtils {
//    //强引用
//    private HashMap<String,Bitmap> memoryCache=new HashMap<>();
//    //软引用
//    private HashMap<String,SoftReference<Bitmap>> softMemoryCache=new HashMap<>();
    private LruCache<String,Bitmap> memoryCache;

    public MemoryCacheUtils() {
        //构造函数来实例化一个LruCache
        long maxMemory=Runtime.getRuntime().maxMemory()/8;
        this.memoryCache = new LruCache<String,Bitmap>((int)maxMemory){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int byteCount= value.getByteCount();
                return byteCount;
            }
        };
    }

    /**
     * 从内存读取bitmap缓存
     * @param url
     * @return
     */
    public Bitmap getBitmapFromMemory(String url){
        Bitmap bitmap=memoryCache.get(url);
        return bitmap;
    }

    /**
     * 设置Bitmap缓存到内存
     * @param url
     * @param bitmap
     */
    public void setBitmapToMemory(String url,Bitmap bitmap){
        memoryCache.put(url,bitmap);
    }
}

本地缓存

public class LocalCacheUtils {
    /**
     * 从本地文件中通过文件名读取缓存图片文件
     * @param url
     * @return
     */
    public Bitmap getBitmapFromLocal(String url) {
        String fileName;
        Bitmap bitmap=null;
        try {
            fileName=Md5.getMD5(url);
            File file=new File(Environment.getExternalStorageDirectory()+"/ImageZip/"+fileName);
            bitmap= BitmapFactory.decodeFile(file.getPath());
        } catch (Exception e) {
            Log.d("info","getBitmapFromLocal wrong");
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 保存缓存图片到本地
     * @param url
     * @param bitmap
     */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
        try {
            String fileName=Md5.getMD5(url);
            File file=new File(Environment.getExternalStorageDirectory()+"/ImageZip/"+fileName);
            if (!file.getParentFile().exists()){
                boolean mkdirs=file.getParentFile().mkdirs();
                Log.d("info","mkdirs:"+mkdirs);
            }
            bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
        }catch (Exception e){
            Log.d("info","setBitmapToLocal wrong");
            e.printStackTrace();
        }

    }
}

网络缓存
在这里网络请求图片用的是AsynTask。

public class NetCacheUtils {
    //内存缓存工具类
    private MemoryCacheUtils memoryCacheUtils;
    //本地缓存工具类
    private LocalCacheUtils localCacheUtils;

    public NetCacheUtils(MemoryCacheUtils memoryCacheUtils, LocalCacheUtils localCacheUtils) {
        this.memoryCacheUtils = memoryCacheUtils;
        this.localCacheUtils = localCacheUtils;
    }

    public void getImageFromNet(ImageView imageView, String url){
        new BitmapTask().execute(imageView,url);
    }

    class BitmapTask extends AsyncTask<Object,Integer,Bitmap>{
        private ImageView imageView;
        private String url;
        @Override
        protected Bitmap doInBackground(Object[] objects) {
            imageView=(ImageView) objects[0];
            url=(String) objects[1];
            return downLoadBitmap(url);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //设置给imageView
            imageView.setImageBitmap(bitmap);
            //保存到本地缓存
            localCacheUtils.setBitmapToLocal(url,bitmap);
            //保存到内存缓存
            memoryCacheUtils.setBitmapToMemory(url,bitmap);
        }
    }
    private Bitmap downLoadBitmap(String url){
        try {
            URL urL = new URL(url);
            HttpURLConnection httpURLConnection = (HttpURLConnection) urL.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setReadTimeout(10000);
            if (httpURLConnection.getResponseCode() == 200) {
                InputStream inputStream = httpURLConnection.getInputStream();
                BitmapFactory.Options options=new BitmapFactory.Options();
                options.inSampleSize=2;
                options.inPreferredConfig=Bitmap.Config.ARGB_4444;
                Bitmap bitmap=BitmapFactory.decodeStream(inputStream,null,options);
                inputStream.close();
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

最后将这三个缓存工具类集成一下:

public class ImageCacheUtils {
    private MemoryCacheUtils memoryCacheUtils;
    private LocalCacheUtils localCacheUtils;
    private NetCacheUtils netCacheUtils;

    public ImageCacheUtils(MemoryCacheUtils memoryCacheUtils, LocalCacheUtils localCacheUtils, NetCacheUtils netCacheUtils) {
        this.memoryCacheUtils = memoryCacheUtils;
        this.localCacheUtils = localCacheUtils;
        this.netCacheUtils = netCacheUtils;
    }
    public void display(ImageView imageView,String url){
        //设置占位符
        imageView.setImageResource(R.mipmap.ic_launcher);
        Bitmap bitmap;
        //从内存缓存中找
        bitmap=memoryCacheUtils.getBitmapFromMemory(url);
        if (bitmap!=null){
            imageView.setImageBitmap(bitmap);
            Log.d("info","从内存缓存加载图片");
            return;
        }
        //内存缓存没有,从本地缓存找
        bitmap=localCacheUtils.getBitmapFromLocal(url);
        if (bitmap!=null){
            imageView.setImageBitmap(bitmap);
            Log.d("info","从本地缓存加载图片");
            //将本地获取的缓存图片保存到内存中
            memoryCacheUtils.setBitmapToMemory(url,bitmap);
            return;
        }
        //本地缓存没有,最后从网络缓存找
        Log.d("info","从网络加载图片");
        netCacheUtils.getImageFromNet(imageView,url);

    }
}

使用:

iv_img = findViewById(R.id.iv_img);
ImageCacheUtils imageCacheUtils=new ImageCacheUtils(memoryCacheUtils,localCacheUtils,netCacheUtils);
imageCacheUtils.display(iv_img,"https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png");

当第一次加载图片的时候,就会用网络去请求,后面就会通过内存或者本地sd卡去加载网络图片了。
当然上面几个类可以通过内部类和单例模式来达到更好的代码结构,为了简单不搞那些了。


以上,图片的三级缓存策略
源码地址:github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,912评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,221评论 11 349
  • 系在腰间的白带 勒紧了你身下的裙摆 那峦挤得多么充盈饱满,都是好看
    零更一阅读 152评论 0 2
  • 总有人以为 分手就是爱情的终点 她们以为 只要分手了 只要不再见面 两个人就能 把以往的一切 当做是过眼云烟 然后...
    幻梦邪魂阅读 234评论 0 1