美文网首页
图片三级缓存策略

图片三级缓存策略

作者: HWilliamgo | 来源:发表于2018-03-21 13:32 被阅读7次

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

    内存缓存

    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

    相关文章

      网友评论

          本文标题:图片三级缓存策略

          本文链接:https://www.haomeiwen.com/subject/ejswqftx.html