Android图片文件缓存

基本设计框架:

  • ImageFileCache构造函数中清理缓存空间。
  • 设计get方法,注意添加时间戳更新,LRU确保删除时最后删除
  • 设计save方法,可以采取压缩方法存放
  • 清理缓存是根据文件修改时间排序后再清理40%空间,清除的都是.cash文件


public class ImageFileCache {
    private static final String CACHDIR = "wantToGoImgCache";
    private static final String WHOLESALE_CONV = ".cach";

    private static final int MB = 1024*1024;
    private static final int CACHE_SIZE = 10;
    private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;

    public ImageFileCache() {
        //清理文件缓存
        removeCache(getDirectory());
    }

    /** 从文件缓存中获取图片 **/
    public Bitmap getImage(final String url) {
        File file = new File(getDirectory(),MD5Util.md5(url)+WHOLESALE_CONV);
        if (file.exists()) {
            //Log.d("ImageFileCache","绝对路径:"+file.getAbsolutePath());
            Bitmap bmp = BitmapFactory.decodeFile(file.getAbsolutePath());
            if (bmp == null) {
                //如果图片文件无法转化为bitmap,则删除该文件
                file.delete();
            } else {
                updateFileTime(file.getAbsolutePath());
                return bmp;
            }
        }else{
            //Log.d("ImageFileCache","文件不存在");
        }
        return null;
    }

    /** 将图片存入文件缓存 **/
    public void saveBitmap(Bitmap bm, String url) {
        if (bm == null) {
            return;
        }
        //判断sdcard上的空间
        if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
            //SD空间不足
            return;
        }
        //进行映射
        String filename = MD5Util.md5(url);
        //获取缓存目录
        File dirFile = getDirectory();
        //缓存目录不存在,建立缓存目录
        if (!dirFile.exists())
            dirFile.mkdirs();
        //新建文件对象
        File file = new File(dirFile,filename);
        try {
            //在缓存文件下创建文件
            file.createNewFile();

            OutputStream outStream = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } catch (FileNotFoundException e) {
            Log.w("ImageFileCache", "FileNotFoundException");
        } catch (IOException e) {
            Log.w("ImageFileCache", "IOException");
        }
    }

    /**
     * 计算存储目录下的文件大小,
     * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
     * 那么删除40%最近没有被使用的文件
     */
    private boolean removeCache(File dirFile) {
        File[] files = dirFile.listFiles();
        if (files == null) {
            return true;
        }
        //判断读写权限
        if (!Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            return false;
        }

        int dirSize = 0;
        for (int i = 0; i < files.length; i++) {
            if (files[i].getName().contains(WHOLESALE_CONV)) {
                dirSize += files[i].length();
            }
        }

        if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
            int removeFactor = (int) ((0.4 * files.length) + 1);
            Arrays.sort(files, new FileLastModifSort());
            for (int i = 0; i < removeFactor; i++) {
                if (files[i].getName().contains(WHOLESALE_CONV)) {
                    files[i].delete();
                }
            }
        }

        if (freeSpaceOnSd() <= CACHE_SIZE) {
            return false;
        }

        return true;
    }

    /** 修改文件的最后修改时间 **/
    public void updateFileTime(String path) {
        File file = new File(path);
        long newModifiedTime = System.currentTimeMillis();
        file.setLastModified(newModifiedTime);
    }

    /** 计算sdcard上的剩余空间 **/
    private int freeSpaceOnSd() {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        //block大小和空闲的block的数量
        double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
        return (int) sdFreeMB;
    }


    /** 获得缓存目录 **/
    private File getDirectory() {
        File dir = new File(getSDPathFile(),CACHDIR);
        return dir;
    }

    /** 取SD卡路径 **/
    private File getSDPathFile() {
        File storageDirectory = null;
        boolean sdCardExist = Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);  //判断sd卡是否存在
        if (sdCardExist) {
            storageDirectory = Environment.getExternalStorageDirectory();  //获取根目录
        }
        return storageDirectory;
    }

    /**
     * 根据文件的最后修改时间进行排序
     */
    private class FileLastModifSort implements Comparator<File> {
        public int compare(File arg0, File arg1) {
            if (arg0.lastModified() > arg1.lastModified()) {
                return 1;
            } else if (arg0.lastModified() == arg1.lastModified()) {
                return 0;
            } else {
                return -1;
            }
        }
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值