图片三级缓存策略

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

内存缓存

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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