图片的三级缓存

三级缓存基本原理

  • 内存缓存:速度很快,不浪费流量,优先
  • 本地缓存:速度快,不浪费流量,其次
  • 网络缓存:速度慢,浪费流量,最后

网络缓存

  • 思路:

    1. 从网络下载图片,通过AsyncTask开启线程,创建HttpURLConnection对象,把输入流转成Bitmap
    2. 因为ListView图片错乱问题,需要给ImageView设置的Tag是图片的url链接,展示图片的时候,比较tag和url是否相等

      代码:
      /**
       * 网络缓存工具类
       */
      public class NetCacheUtils {
          private static final String TAG = "NetCacheUtils";
      
          public void getBitmapFromNet(ImageView imageView, String url) {
              //异步下载图片
              new BitmapTask(imageView, url).execute(imageView, url);
          }
      
          class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
              private ImageView imageView;
              private String url;
              public BitmapTask(ImageView imageView, String url) {
                  this.imageView = imageView;
                  this.url = url;
                  this.imageView.setTag(this.url);
              }
      
              @Override
              protected void onPreExecute() {
                  super.onPreExecute();
              }
      
              @Override
              protected Bitmap doInBackground(Object... params) {
                  //使用url下载图片
                  Bitmap bitmap = download(url);      
                  return bitmap;
              }
      
              @Override
              protected void onPostExecute(Bitmap result) {
                  //给ImageView设置图片
                  //由于ListView的重用机制,
                  // 导致某个item有可能展示它所重用的那个item的图片,导致图片错乱
                  //解决方案:确保当前设置的图片和当前显示的imageView完全匹配
                  if (result != null) {
                      String url = (String) imageView.getTag();
                      //判断当前下载的图片的url是否和ImageView的url一致,如果一致,说明完全匹配
                      if (this.url.equals(url)) {
                          imageView.setImageBitmap(result);
                          Log.i(TAG, "onPostExecute: 从网络上下载图片啦");
                      }
                  }
              }
          }
      
          //下载图片
          private Bitmap download(String url) {
              HttpURLConnection conn = null;
              try {
                  conn = (HttpURLConnection) new URL(url).openConnection();
                  conn.setRequestMethod("GET");
                  conn.setConnectTimeout(6000);//设置连接超时
                  conn.setReadTimeout(6000);//设置读取超时
                  conn.connect();//连接
                  int responseCode = conn.getResponseCode();//获取返回码
                  if (responseCode == 200) {
                      InputStream in = conn.getInputStream();//获取输入流
                      //使用输入流生成Bitmap对象
                      Bitmap bitmap = BitmapFactory.decodeStream(in);
                      return bitmap;
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }finally {
                  if (conn != null) {
                      conn.disconnect();
                  }
              }
              return null;
          }
      }
      

本地缓存

  • 思路:

    1. 创建本地缓存工具,首先创建缓存目录,图片url通过MD5加密作为文件名
    2. 从网络下载图片后,保存图片到本地
    3. 展示图片时,首先根据url判断本地是否有缓存,如果有就读取本地缓存,没有就从网上下载

    代码:
    /**
    * 本地缓存工具类
    */
    public class LocalCacheUtils {
    //缓存文件夹
    private String PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + “/zhbj_cache/”;

            //写缓存
            public void setLocalCache(String url, Bitmap bitmap) {
                //将图片保存在本地文件中
                File dir = new File(PATH);
                if (!dir.exists() || !dir.isDirectory()) {
                    dir.mkdirs();//创建文件夹
                }
                try {
                    File cacheFile = new File(dir, MD5Encoder.encode(url));
                    //将图片压缩保存到本地,参数1:图片的格式,参数2:压缩比(0-100), 参数3:输出流
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(cacheFile));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            //读缓存
            public Bitmap getLocalCache(String url) {
                try {
                    File cacheFile = new File(PATH, MD5Encoder.encode(url));
                    if (cacheFile.exists()) {
                        //缓存存在
                        Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(cacheFile));
                        return bitmap;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    

内存缓存

  • 思路:

    1. 创建HashMap,key是url,value是Bitmap
    2. 从网络下载图片展示后,把bitmap存放到HashMap中,从本地缓存中读取图片展示后,把bitmap存放到HashMap中
    3. 展示图片时,如果内存缓存有bitmap,则不需要从本地或者网络加载图片

      代码:
          /**
           * 内存缓存
           */
          public class MemoryCacheUtils {
              private Map<String, Bitmap> mHashMap = new HashMap<>();
              //写缓存
              public void setMemoryCache(String url, Bitmap bitmap) {
                  mHashMap.put(url, bitmap);
              }
      
              //读缓存
              public Bitmap getMemroyCache(String  url) {
                  return mHashMap.get(url);
              }
          }
      

四个引用

  1. 强引用,StrongReference,默认,垃圾回收器不回收
  2. 软引用,SoftReference,内存不足时,垃圾回收器考虑回收
  3. 弱引用,WeakReference,内存不足时,垃圾回收器更会考虑回收
  4. 虚引用,PhantomReference,内存不足时,垃圾回收器最会考虑回收

思路:
1. 把bitmap用SoftReference包装起来,然后再存放到map集合中
2. 读取时先获取SoftReference对象,再从软引用对象中获取bitmap

    获取虚拟机分配的最大内存,默认16M
     long maxMemory = Runtime.getRuntime().maxMemory();
       maxSize,内存缓存上限        
       mLruCache = new LruCache<String, Bitmap>((int) (maxMemory/8)){
                        //返回单个对象占用内存的大小
                        @Override
                        protected int sizeOf(String key, Bitmap value) {
                            int byteCount = value.getRowBytes() * value.getHeight();
                            return byteCount;
                        }
                    };      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值