一个简单的Volley图片二级缓存

话不多说,附上自己的代码

package com.hsd13.util.volley;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;

import com.android.volley.toolbox.ImageLoader;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Created by violetMoon on 2015/10/28.
 */
public class ImageCache implements ImageLoader.ImageCache {

    private static ImageCache instance;

    private android.util.LruCache<String, Bitmap> mMemCache;

    private static final String DISK_CACHE_DIR = "bitmap";
    private static final long DISK_CACHE_SIZE = 50 * 1024 * 1024;
    private static final int IO_BUFFER_SIZE  =8 * 1024;
    private static final int DISK_ITEM_INDEX = 0;
    private DiskLruCache mDiskCache;

    private int memHitCount;
    private int diskHitCount;
    private int requestCount;

    private ImageCache(Context context) {
        initMemCache();
        initDiskCache(context);
    }

    public static ImageCache getInstance(Context context) {
        if (instance == null)
            instance = new ImageCache(context);
        return instance;
    }

    private void initMemCache() {
        long maxMem = Runtime.getRuntime().maxMemory();
        int cacheMem = (int)maxMem / 8;
        mMemCache = new android.util.LruCache<String, Bitmap>(cacheMem) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
            }
        };
    }

    private void initDiskCache(Context context) {
        File cacheFile = getDiskCachDir(context, DISK_CACHE_DIR);
        if (!cacheFile.exists())
            cacheFile.mkdirs();

        if (getUsableSpace(cacheFile) > DISK_CACHE_SIZE) {
            try {
                mDiskCache = DiskLruCache.open(cacheFile, 1, 1, DISK_CACHE_SIZE);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /** TODO: android6.0权限检测
     * 获取缓存的文件夹,如果外存{@link Context#getExternalCacheDir()}可用,则选择在外存中缓存图片,
     * 否则在内存{@link Context#getCacheDir()}中缓存
     * @param context
     * @return
     */
    private File getDiskCachDir(Context context, String subDirName) {
        boolean externStorageAvailable = Environment.getExternalStorageState()
                .equals(Environment.MEDIA_MOUNTED);
        String cachePath;
        if (externStorageAvailable) {
            cachePath = context.getExternalCacheDir().getPath();
            DEBUG.log("ImageCache", "cache to extern");
        } else {
            cachePath = context.getCacheDir().getPath();
            DEBUG.log("ImageCache", "cache to internal");
        }
        return new File(cachePath + File.separator + subDirName);
    }

    private static long getUsableSpace(File dir) {
        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD)
            return dir.getUsableSpace();
        StatFs statFs = new StatFs(dir.getPath());
        //getBlockSizeLong要求api18
        return (long)statFs.getBlockSize() * statFs.getAvailableBlocks();
    }

    @Override
    public Bitmap getBitmap(String url) {
        DEBUG.log("ImageCache", "getBitmap:" + url);
        requestCount++;

        String key = getKey(url);
        Bitmap memCacheBitmap = loadFromMemCache(key);
        if (memCacheBitmap != null)
            return memCacheBitmap;

        Bitmap diskCacheBitmap = loadFromDiskCache(key);
        return diskCacheBitmap;
    }

    /**
     * 缓存命中率
     * @return
     */
    public double getHitRate() {
        if (requestCount != 0)
            return (double)(memHitCount + diskHitCount) / requestCount;
        else
            return 0.0;
    }

    private String getKey(String url) {
        //url中的特殊字符会影响缓存,DiskLruCache里面对key的处理是用LinkedHashMap,
        // 但我直接在JavaSE上试的时候是可以的,具体原因不明
        return Utility.getMD5(url);
    }

    private Bitmap loadFromMemCache(String key) {
        Bitmap bitmap = mMemCache.get(key);
        if (bitmap != null) {
            memHitCount++;
            DEBUG.log("ImageCache", "mem cache hit");
        }
        return bitmap;
    }

    private Bitmap loadFromDiskCache(String key) {
        if (mDiskCache == null)
            return null;

        Bitmap bitmap = null;
        try {
            DiskLruCache.Snapshot snapshot = mDiskCache.get(key);
            if (snapshot != null) {
                diskHitCount++;
                DEBUG.log("ImageCache", "disk cache hit");
                FileInputStream in = (FileInputStream) snapshot.getInputStream(DISK_ITEM_INDEX);
                bitmap = BitmapFactory.decodeStream(in);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        DEBUG.log("ImageCache", "putBitmap:" + url);

        String key = getKey(url);
        if (mMemCache.get(key) == null)
            mMemCache.put(key, bitmap);

        if(mDiskCache == null)
            return;
        BufferedOutputStream out = null;
        try {
            DiskLruCache.Editor editor = mDiskCache.edit(key);
            if (editor != null) {
                out = new BufferedOutputStream(
                        editor.newOutputStream(DISK_ITEM_INDEX), IO_BUFFER_SIZE);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            FileUtils.close(out);
        }
    }

    public void clearCache(Context context) {
        if (mDiskCache == null)
            return;
        try {
            mDiskCache.delete();
            initDiskCache(context);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值