Android 本地圖片快取
阿新 • • 發佈:2018-12-07
廢話
每次從記憶體裡面讀圖片,圖片小的話還好,圖片大的話比較吃力,速度慢不說,還容易因為記憶體問題出現崩潰。
後來加上了快取,從快取中讀取,結果發現,還是會爆炸,檢查一下發現,一張拍照3M多,直接把整個快取區都炸開了,既然找到問題了,也就好解決了。
所以就加上了個壓縮,邏輯是:1-從快取中讀取 2-讀取不到,先從記憶體中讀取,同時非同步壓縮圖片 3-壓縮完成之後寫入快取 4-再次讀取可以在快取中找到
工具
(快取工具)Lrucache:https://blog.csdn.net/jxxfzgy/article/details/44885623
(圖片壓縮)魯班壓縮:https://github.com/Curzibn/Luban
程式碼
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.text.TextUtils; import android.util.LruCache; import java.io.File; import top.zibin.luban.CompressionPredicate; import top.zibin.luban.Luban; import top.zibin.luban.OnCompressListener; /** * 圖片快取類(僅供快取本地圖片使用) */ public class LruCacheUtils { private static LruCache<String, Bitmap> mMemoryCache; /** * 初始化(必須),推薦在Application中啟動,一次就可以了 */ public static void init() { int maxMemory = (int) (Runtime.getRuntime().maxMemory()); // 使用最大可用記憶體值的1/8作為快取的大小。 int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { protected int sizeOf(String key, Bitmap bitmap) { //在每次存入快取的時候呼叫 return bitmap.getByteCount() / 1024; } }; } /** * 將bitmap加入到快取中 * * @param path LruCache的鍵,即圖片的下載路徑 * @param bitmap LruCache的值,即圖片的Bitmap物件 */ public static void addImage(String path, Bitmap bitmap) { if (mMemoryCache.get(path) == null) { mMemoryCache.put(path, bitmap); } } /** * 讀取快取中的圖片,不需要壓縮 * * @param path * @return */ public static Bitmap getImage(String path) { Bitmap bitmap = mMemoryCache.get(path); if (bitmap != null) { return bitmap; } bitmap = BitmapFactory.decodeFile(path); if (bitmap != null) { addImage(path, bitmap); } return bitmap; } /** * 讀取快取中的圖片,需要壓縮 * * @param path * @return */ public static Bitmap getImage(Context context, final String path) { Bitmap bitmap = mMemoryCache.get(path); if (bitmap != null) { //充快取裡面讀取 return bitmap; } //快取裡面還沒有 bitmap = BitmapFactory.decodeFile(path);//直接從檔案中讀取Bitmap出來 if (bitmap != null) { String cachePath = PathUtils.getImgCache();//壓縮之後的檔案存放的資料夾,自己設定 Luban.with(context) .load(path) .ignoreBy(288)//不壓縮的閾值,單位為K .setTargetDir(cachePath) .filter(new CompressionPredicate() { @Override public boolean apply(String path) { return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); } }) .setCompressListener(new OnCompressListener() { @Override public void onStart() { // TODO 壓縮開始前呼叫,可以在方法內啟動 loading UI } @Override public void onSuccess(File file) { // TODO 壓縮成功後呼叫,返回壓縮後的圖片檔案 Bitmap bitmap1 = BitmapFactory.decodeFile(file.getPath()); // ALog.e("壓縮成功:" + file.length()); addImage(path, bitmap1); MyFileUtils.deleteFile(file);//已經快取完成了,刪除壓縮好的檔案 } @Override public void onError(Throwable e) { // TODO 當壓縮過程出現問題時呼叫 // ALog.e("壓縮出錯:" + e.toString()); addImage(path, BitmapFactory.decodeFile(path));//壓縮失敗,直接快取(很少出現) } }).launch(); } return bitmap; } }
呼叫:
Bitmap bitmap=LruCacheUtils.getImage(getContext(),path);