1. 程式人生 > >Android 本地圖片快取

Android 本地圖片快取

廢話

每次從記憶體裡面讀圖片,圖片小的話還好,圖片大的話比較吃力,速度慢不說,還容易因為記憶體問題出現崩潰。

後來加上了快取,從快取中讀取,結果發現,還是會爆炸,檢查一下發現,一張拍照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);