ImageLoader LruCache DisLruCache 雙緩存

ngl1125 8年前發布 | 7K 次閱讀 Bitmap 安卓開發 Android開發 移動開發

緩存?

內存緩存跟磁盤緩存,有這種一個概念,當第一次加載完數據之后保存到內存或者磁盤,當再次讀取的時候。我們就可以>先去讀硬盤里面的緩存,如果沒有則讀內存;如果在沒有則去加載網絡請求;

為何要雙緩存?

可以打開微信, 然后發一個消息或者是讀取一張照片,而后你再次打開著張照片的時候就直接從內存里面讀取;

之后你再關閉網絡, 然后你在重新進入app你會發現一樣是可以獲取到之前緩存的信息的;

那大概就是他們緩存進的不僅僅是內存還緩存到sd里面, 當沒有網絡的時候直接從sd里面讀取緩存;

LruCache DisLruCache;

我們先看如下一段代碼 初始化ImageLoader

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> 

當實例化ImageCache 重寫兩個方法; 根據名稱就能知道兩個方法的作用;

先放上兩段代碼

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);
    }

以上就是是一個典型的內存緩存;

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();
    }
}

以上代碼則是硬盤緩存,要注意的地方都已經寫上注釋了;

那么這個緩存是在什么時候調用呢?

這里呢其實不需要我們擔心,因為ImageLoad 已經在內部幫我們做好了

看以下我自己運行的demo;

這是第一次使用加載圖片

可以清楚的看到加載中的圖片

這是讀取緩存好的并沒有出現加載中的照片,非常流暢;

 

 

來自:http://www.jianshu.com/p/e3ce0161cfa9

 

 本文由用戶 ngl1125 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!