ImageLoader LruCache DisLruCache 双缓存

ngl1125 8年前
   <h2><strong>缓存?</strong></h2>    <p>内存缓存跟磁盘缓存,有这种一个概念,当第一次加载完数据之后保存到内存或者磁盘,当再次读取的时候。我们就可以>先去读硬盘里面的缓存,如果没有则读内存;如果在没有则去加载网络请求;</p>    <h2><strong>为何要双缓存?</strong></h2>    <p>可以打开微信, 然后发一个消息或者是读取一张照片,而后你再次打开着张照片的时候就直接从内存里面读取;</p>    <p>之后你再关闭网络, 然后你在重新进入app你会发现一样是可以获取到之前缓存的信息的;</p>    <p>那大概就是他们缓存进的不仅仅是内存还缓存到sd里面, 当没有网络的时候直接从sd里面读取缓存;</p>    <h2><strong>LruCache DisLruCache;</strong></h2>    <p>我们先看如下一段代码 初始化ImageLoader</p>    <pre>  <code class="language-java">ImageLoader imageLoader = new ImageLoader(MyQueue.getInstance(context), new ImageLoader.ImageCache() {             //  根据url获取Bitmap              @Override              public Bitmap getBitmap(String url) {                  return null;              }              //url作为表示保存Bitmap                 @Override              public void putBitmap(String url, Bitmap bitmap) {                }          })</code></pre>    <p>当实例化ImageCache 重写两个方法; 根据名称就能知道两个方法的作用;</p>    <p>先放上两段代码</p>    <pre>  <code class="language-java">private Context mContext;      private LruCache<String,Bitmap> lruCache;      public MyLruCache(Context context) {          this.mContext = context;        //最大缓存容量          int maxSize = 10 * 1024 * 1024;          lruCache = new LruCache<String, Bitmap>(maxSize) {              @Override              protected int sizeOf(String key, Bitmap value) {                  return value.getHeight() * value.getRowBytes();              }          };      }      @Override      public Bitmap getBitmap(String url) {          return lruCache.get(url);      }        @Override      public void putBitmap(String s, Bitmap bitmap) {          lruCache.put(s,bitmap);      }</code></pre>    <p>以上就是是一个典型的内存缓存;</p>    <pre>  <code class="language-java">public class MySystemDiskLru {      public DiskLruCache mDiskLruCache = null;      private static MySystemDiskLru mySystemDiskLru;      public Context context;        private MySystemDiskLru(Context context) {          this.context = context;          try {              mDiskLruCache = DiskLruCache.open(getDirectory("VolleyImageCache"),                      AppUtils.getVersionCode(context), 1, 10 * 1024 * 1024);          } catch (IOException e) {              e.printStackTrace();          }      }        // 单列      public static MySystemDiskLru getInstance(Context context) {          if (mySystemDiskLru == null) {              mySystemDiskLru = new MySystemDiskLru(context);          }          return mySystemDiskLru;      }        /**       * 获取缓存地址       */      public File getDirectory(String PathName) {          String path = null;          if (SDCardUtils.isSDCardEnable()) {              path = SDCardUtils.getSDCardPath() + PathName;          } else {              path = SDCardUtils.getRootDirectoryPath() + PathName;          }          File file = new File(path);          if (file.exists()) {              file.mkdirs();          }          Log.i("TAG","------path-" + path);          return file;      }        /**       * 保存       **/      public void save(String url, Bitmap bitmap) {          BufferedOutputStream os = null;          OutputStream outputStream = null;          DiskLruCache.Editor editor = null;            String key = hashKeyForDisk(url);          try {              editor = mDiskLruCache.edit(key);              if (editor != null) {                  os = new BufferedOutputStream(editor.newOutputStream(0));  //                利用Bitmap工具类,将Bitmap转换成输入流                  os.write(BitmapUtils.compressBitmap(bitmap));              }              /** 切记刷新 */              os.flush();              editor.commit();              mDiskLruCache.flush();          } catch (IOException e) {              e.printStackTrace();              // 如果没成功数据回滚              try {                  editor.abort();              } catch (IOException e1) {                  e1.printStackTrace();              }            } finally {              if (os != null) {                  try {                      os.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }      }        /**       * 获取       **/      public Bitmap getBitmap(String url) {          Bitmap bitmap = null;          InputStream is = null;          DiskLruCache.Snapshot snapshot = null;            String key = hashKeyForDisk(url);          try {              snapshot = mDiskLruCache.get(key);              // 利用了工厂将io流转换成bitmap              if (snapshot != null) {                  is = snapshot.getInputStream(0);  //                Options op = new Options();  //                op.inSampleSize = 4; ,new Rect(),op  //                try {                  bitmap = BitmapFactory.decodeStream(is);  //                } catch (OutOfMemoryError err) {  //                    Log.e("", "====oom-----------");  //                }              }          } catch (IOException e) {              e.printStackTrace();          } finally {              try {                  if (is != null) {                      is.close();                  }              } catch (IOException e) {                  e.printStackTrace();              }          }          return bitmap;      }        /**       * 将Url文件转换成MD5唯一标示       */      public String hashKeyForDisk(String key) {          String cacheKey;          try {              final MessageDigest mDigest = MessageDigest.getInstance("MD5");              mDigest.update(key.getBytes());              cacheKey = bytesToHexString(mDigest.digest());          } catch (NoSuchAlgorithmException e) {              cacheKey = String.valueOf(key.hashCode());          }          return cacheKey;      }        private String bytesToHexString(byte[] bytes) {          StringBuilder sb = new StringBuilder();          for (int i = 0; i < bytes.length; i++) {              String hex = Integer.toHexString(0xFF & bytes[i]);              if (hex.length() == 1) {                  sb.append('0');              }              sb.append(hex);          }          return sb.toString();      }  }</code></pre>    <p>以上代码则是硬盘缓存,要注意的地方都已经写上注释了;</p>    <h2><strong>那么这个缓存是在什么时候调用呢?</strong></h2>    <p>这里呢其实不需要我们担心,因为ImageLoad 已经在内部帮我们做好了</p>    <p>看以下我自己运行的demo;</p>    <p>这是第一次使用加载图片</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c8fd927e03d2aee57a8321d191c0929b.gif"></p>    <p>可以清楚的看到加载中的图片</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/171e94b30e9df022fe732e4e5cbd029a.gif"></p>    <p>这是读取缓存好的并没有出现加载中的照片,非常流畅;</p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/e3ce0161cfa9</p>    <p> </p>