Android local picture cache

Posted by Operandi on Mon, 30 Dec 2019 20:48:38 +0100

Crap

Every time I read a picture from memory, it's ok if the picture is small. If the picture is large, it's hard. It's slow. It's easy to crash because of memory problems.

Later, the cache was added and read from the cache. It was found that it would still explode. After checking, it was found that more than 3M of a photo directly exploded the whole cache area. Now that the problem was found, it would be solved.

So a compression is added. The logic is: 1 - read from the cache; 2 - not read from the cache. Read from the memory first, and compress the image asynchronously; 3 - write to the cache after compression; 4 - read again and find it in the cache

tool

(caching tool) Lrucache:https://blog.csdn.net/jxxfzgy/article/details/44885623

(picture compression) Luban compression: https://github.com/Curzibn/Luban

Code


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;

/**
 * Picture cache class (only used to cache local pictures)
 */
public class LruCacheUtils {
    private static LruCache<String, Bitmap> mMemoryCache;

    /**
     * Initialization (required). It is recommended to start in Application. One time is OK
     */
    public static void init() {
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        // Use 1 / 8 of the maximum available memory value as the size of the cache.
        int cacheSize = maxMemory / 8;
        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            protected int sizeOf(String key, Bitmap bitmap) {
                //Called every time a cache is stored
                return bitmap.getByteCount() / 1024;
            }
        };
    }

    /**
     * Add bitmap to the cache
     *
     * @param path   LruCache The download path of the picture
     * @param bitmap LruCache The Bitmap object of the picture
     */
    public static void addImage(String path, Bitmap bitmap) {
        if (mMemoryCache.get(path) == null) {
            mMemoryCache.put(path, bitmap);
        }
    }

    /**
     * Read the pictures in the cache without compression
     *
     * @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;
    }

    /**
     * To read the pictures in the cache, you need to compress them
     *
     * @param path
     * @return
     */
    public static Bitmap getImage(Context context, final String path) {
        Bitmap bitmap = mMemoryCache.get(path);
        if (bitmap != null) {
            //Read from cache
            return bitmap;
        }
        //Not in the cache yet
        bitmap = BitmapFactory.decodeFile(path);//Read Bitmap directly from the file
        if (bitmap != null) {
            String cachePath = PathUtils.getImgCache();//The folder where the compressed files are stored, set by yourself
            Luban.with(context)
                    .load(path)
                    .ignoreBy(288)//Uncompressed threshold in 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 calls before compression starts, and loading UI can be started in the method.
                        }

                        @Override
                        public void onSuccess(File file) {
                            // After TODO compression is successful, it returns the compressed picture file.
                            Bitmap bitmap1 = BitmapFactory.decodeFile(file.getPath());
//                            Log. E ("compression succeeded:" + file.length());
                            addImage(path, bitmap1);
                            MyFileUtils.deleteFile(file);//Cache completed, delete compressed file
                        }

                        @Override
                        public void onError(Throwable e) {
                            // TODO called when there is a problem with the compression process
//                            Log. E ("compression error:" + e.toString());
                            addImage(path, BitmapFactory.decodeFile(path));//Compression failed, direct cache (rare)
                        }
                    }).launch();
        }
        return bitmap;
    }

}

Call:

Bitmap bitmap=LruCacheUtils.getImage(getContext(),path);

Topics: Android github Java