Glide图片框架使用详细介绍(二)之缓存策略

一、
上篇文章我们了解到
Glide的基本使用很简单,且可配置度高

http://blog.csdn.net/qq_37237245/article/details/72956121

 Glide.with(this).load(url).into(imageView);

和其他三级缓存一样,Glide的缓存读取顺序是 内存–>磁盘–>网络

需要注意的是Glide的内存缓存和磁盘缓存的配置相互没有直接影响,所以可以同时进行配置

首先你要知道,默认情况下,Glide自动就是开启内存缓存和磁盘缓存的。也就是说,当我们使用Glide加载了一张图片之后,这张图片就会被缓存到内存当中,只要在它还没从内存中被清除之前,下次使用Glide再加载这张图片都会直接从内存当中读取,而不用重新从网络或硬盘上读取了,这样无疑就可以大幅度提升图片的加载效率。比方说你在一个RecyclerView当中反复上下滑动,RecyclerView中只要是Glide加载过的图片都可以直接从内存当中迅速读取并展示出来,从而大大提升了用户体验。

二、

1、缓存资源

Glide的缓存资源分为两种:

1.原图(SOURCE) :原始图片
2.处理图(RESULT) :经过压缩和变形等处理后的图片

2、内存缓存

默认情况下,Glide自动就是开启内存缓存.skipMemoryCache(true) 不必要配置,当然如果禁止内存缓存,可以改成false
Glide默认是会在内存中缓存处理图(RESULT),而不是原图。
因此使用Glide,我们就完全不用担心图片内存浪费,甚至是内存溢出的问题。因为Glide从来都不会直接将图片的完整尺寸全部加载到内存中,而是用多少加载多少。Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。

Glide.with(this)
     .load(url)
     .skipMemoryCache(true)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

3、磁盘缓存

.diskCacheStrategy(DiskCacheStrategy.ALL)的参数分四个

1.ALL:缓存原图(SOURCE)和处理图(RESULT)

2.NONE:什么都不缓存

3.SOURCE:只缓存原图(SOURCE)

4.RESULT:只缓存处理图(RESULT) —默认值

Picasso和Glide在磁盘缓存策略上有很大的不同。Picasso缓存无论怎么改都只是缓存一张全尺寸原图,使用时候再调整适应imageview大小。而Glide缓存默认的是跟ImageView尺寸相同的。Glide则不同,它会为每种大小的ImageView缓存 一次。
尽管一张图片已经缓存了一次,但是假如你要在另外一个地方再次以不同尺寸显示,需要重新下载,调整成新尺寸的大小,然后将这个尺寸的也缓存起来

具体说来就是:假如在第一个页面有一个200x200的ImageView,在第二个页面有一个100x100的ImageView,这两个ImageView本来是要显示同一张图片,却需要下载两次。

不过,你可以改变这种行为,让Glide既缓存原图又缓存处理图:

Glide.with(this)
     .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
     .diskCacheStrategy(DiskCacheStrategy.ALL)
     .into(ivImgGlide);

下次在任何ImageView中加载图片的时候,全尺寸的图片将从缓存中取出,重新调整大小,然后缓存。加载很快。

4.缓存大小及路径

最大空间:

Glide的内存缓存其实涉及到比较多的计算,这里就介绍最重要的一个参数,就是内存缓存最大空间

内存缓存最大空间(maxSize)=每个进程可用的最大内存 * 0.4

(低配手机的话是: 每个进程可用的最大内存 * 0.33)

磁盘缓存大小

磁盘缓存大小: 250 * 1024 * 1024(250MB)

    /** 250 MB of cache. */
    int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;

磁盘缓存目录

磁盘缓存目录: 项目/cache/image_manager_disk_cache

    String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";

5、清除缓存

由于Glide可能会缓存一张图片的多个分辨率的图片,并且文件名是被哈希过的,所以并不能很好的删除单个资源的缓存,以下是官方文档中的描述

Because File names are hashed keys, there is no good way to simply delete all of the cached files on disk that correspond to a particular url or file path. The problem would be simpler if you were only ever allowed to load
or cache the original image, but since Glide also caches thumbnails and provides various transformations, each of which will result in a new File in the cache, tracking down and deleting every cached version of an image 
is difficult.

In practice, the best way to invalidate a cache file is to change your identifier when the content changes 
(url, uri, file path etc).

清除所有内存缓存(需要在Ui线程操作)

Glide.get(this).clearMemory();

清除所有磁盘缓存(需要在子线程操作)

Glide.get(MainActivity.this).clearDiskCache();

注: 在使用中的资源不会被清除

三、清除缓存以及工具类

获取Glide磁盘缓存大小

public String getCacheSize() {
    try {
        return getFormatSize(getFolderSize(new File(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR)));
    } catch (Exception e) {
        e.printStackTrace();
        return "获取失败";
    }
}

清除Glide磁盘缓存

public boolean cleanCatchDisk() {
    return deleteFolderFile(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR, true);
}

public boolean clearCacheDiskSelf() {
    try {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Glide.get(Application.getInstance()).clearDiskCache();
                }
            }).start();
        } else {
            Glide.get(Application.getInstance()).clearDiskCache();
        }
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

封装工具类

package com.yaphetzhao.glidecatchsimple.glide;

import android.os.Looper;
import android.util.Log;

import com.bumptech.glide.Glide;
import com.yaphetzhao.glidecatchsimple.Application;
import com.yaphetzhao.glidecatchsimple.glide.config.GlideCatchConfig;

import java.io.File;
import java.math.BigDecimal;

/**
 * Created by YaphetZhao
 * on 2016/12/19.
 * <p>
 * QQ:11613371
 * GitHub:https://github.com/YaphetZhao
 * Email:yaphetzhao@foxmail.com
 * Email_EN:yaphetzhao@gmail.com
 * <p>
 * Glide缓存工具类
 */
@SuppressWarnings("ResultOfMethodCallIgnored")
public class GlideCatchUtil {
    private static GlideCatchUtil instance;

    public static GlideCatchUtil getInstance() {
        if (null == instance) {
            instance = new GlideCatchUtil();
        }
        return instance;
    }

    // 获取Glide磁盘缓存大小
    public String getCacheSize() {
        try {
            return getFormatSize(getFolderSize(new File(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR)));
        } catch (Exception e) {
            e.printStackTrace();
            return "获取失败";
        }
    }

    // 清除Glide磁盘缓存,自己获取缓存文件夹并删除方法
    public boolean cleanCatchDisk() {
        return deleteFolderFile(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR, true);
    }

    // 清除图片磁盘缓存,调用Glide自带方法
    public boolean clearCacheDiskSelf() {
        try {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Glide.get(Application.getInstance()).clearDiskCache();
                    }
                }).start();
            } else {
                Glide.get(Application.getInstance()).clearDiskCache();
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 清除Glide内存缓存
    public boolean clearCacheMemory() {
        try {
            if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行
                Glide.get(Application.getInstance()).clearMemory();
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    // 获取指定文件夹内所有文件大小的和
    private long getFolderSize(File file) throws Exception {
        long size = 0;
        try {
            File[] fileList = file.listFiles();
            for (File aFileList : fileList) {
                if (aFileList.isDirectory()) {
                    size = size + getFolderSize(aFileList);
                } else {
                    size = size + aFileList.length();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return size;
    }

    // 格式化单位
    private static String getFormatSize(double size) {
        double kiloByte = size / 1024;
        if (kiloByte < 1) {
            return size + "Byte";
        }
        double megaByte = kiloByte / 1024;
        if (megaByte < 1) {
            BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
            return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
        }
        double gigaByte = megaByte / 1024;
        if (gigaByte < 1) {
            BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
            return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
        }
        double teraBytes = gigaByte / 1024;
        if (teraBytes < 1) {
            BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
            return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
        }
        BigDecimal result4 = new BigDecimal(teraBytes);
        return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
    }

    // 按目录删除文件夹文件方法
    private boolean deleteFolderFile(String filePath, boolean deleteThisPath) {
        try {
            File file = new File(filePath);
            if (file.isDirectory()) {
                File files[] = file.listFiles();
                for (File file1 : files) {
                    deleteFolderFile(file1.getAbsolutePath(), true);
                }
            }
            if (deleteThisPath) {
                if (!file.isDirectory()) {
                    file.delete();
                } else {
                    if (file.listFiles().length == 0) {
                        file.delete();
                    }
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值