1、在 Glide 中配置缓存的方式
首先,我们可以在自定义的 GlideModule 中制定详细的缓存策略。即在 applyOptions()
中通过直接调用 GlideBuilder
的方法来指定缓存的信息:
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, DISK_CACHE_DIR, DISK_CACHE_SIZE));
builder.setMemoryCache(...);
builder.setDiskCache(...);
// ... 略
}
另外,我们在每个图片加载请求中自定义当前图片加载请求的缓存策略,
Glide.with(getContext())
.load("https://3-im.guokr.com/0lSlGxgGIQkSQVA_Ja0U3Gxo0tPNIxuBCIXElrbkhpEXBAAAagMAAFBO.png")
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC))
.apply(RequestOptions.skipMemoryCacheOf(false))
.into(getBinding().iv);
以上是两个比较常用的缓存的配置方式,具体的 API 可以查看相关的源码了解.
不论 Glide 还是其他的框架的缓存无非就是基于内存的缓存和基于磁盘的缓存两种,而且缓存的管理算法基本都是 LRU. 针对内存缓存,Android 中提供了 LruCache
,笔者在之前的文章中曾经分析过这个框架:
《Android 内存缓存框架 LruCache 的源码分析》
至于磁盘缓存, Glide 和 OkHttp 都是基于 DiskLruCache 进行了封装。这个框架本身的逻辑并不复杂,只是指定了一系列缓存文件的规则,读者可以自行查看源码学习。本文中涉及上述两种框架的地方不再详细追究缓存框架的源码。
2、Glide 缓存的源码分析
2.1 缓存配置
首先, 我们在 applyOptions()
方法中的配置会在实例化单例的 Glide 对象的时候被调用. 所以, 这些方法的作用范围是全局的, 对应于整个 Glide. 下面的方法是 RequestBuilder
的 build()
方法, 也就是我们最终完成构建 Glide 的地方. 我们可以在这个方法中了解 RequestBuilder
为我们提供了哪些与缓存相关的方法. 以及默认的缓存配置.
Glide build(@NonNull Context context) {
// ... 无关代码, 略
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) {
// 默认的缓存配置
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
engine = new Engine(/*各种参数*/);
}
return new Glide(/*各种方法*/);
}
这里我们对 MemorySizeCalculator
这个参数进行一些说明. 顾名思义, 它是缓存大小的计算器, 即用来根据当前设备的环境计算可用的缓存空间 (主要针对的时基于内存的缓存).
MemorySizeCalculator(MemorySizeCalculator.Builder builder) {
this.context = builder.context;
arrayPoolSize =
isLowMemoryDevice(builder.activityManager)
? builder.arrayPoolSizeBytes / LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR
: builder.arrayPoolSizeBytes;
// 计算APP可申请最大使用内存,再乘以乘数因子,内存过低时乘以0.33,一般情况乘以0.4
int maxSize =
getMaxSize(
builder.activityManager, builder.maxSizeMultiplier, builder.lowMemoryMaxSizeMultiplier);
// ARGB_8888 ,每个像素占用4个字节内存
// 计算屏幕这么大尺寸的图片占用内存大小
int screenSize = widthPixels * heightPixels * BYTES_PER_ARGB_8888_PIXEL;
// 计算目标位图池内存大小
int targetBitmapPoolSize