Glide配置:AppGlideModule
Glide用起来非常方便,基本用法见Glide的基本用法,简短的一句链式调用就能给ImageView设置图片。而且自带缓存实现,如果不进行额外的设置Glide的缓存目录、缓存大小都是默认的。应用可以自行进行定制修改,就用到AppGlideModule。
1、自定义AppGlideModule
配置Glide加载图片的设置、缓存设置、缓存策略,就需要应用自己继承AppGlideModule类,实现里面的空方法:
public class ApplicationGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
super.applyOptions(context, builder);
}
@Override
public boolean isManifestParsingEnabled() {
return super.isManifestParsingEnabled();
}
}
2、GlideBuilder
applyOptions(Context context,GlideBuilder builder)方法就是我们需要关注的,传入的GlideBuilder类型参数,典型的创建者模式,用来创建Glide实例(Glide是单例的)。其中有非常多的配置项:
/** A builder class for setting default structural classes for Glide to use. */
@SuppressWarnings("PMD.ImmutableField")
public final class GlideBuilder {
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
private Engine engine;
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
private MemoryCache memoryCache;
private GlideExecutor sourceExecutor;
private GlideExecutor diskCacheExecutor;
private DiskCache.Factory diskCacheFactory;
private MemorySizeCalculator memorySizeCalculator;
private ConnectivityMonitorFactory connectivityMonitorFactory;
...
}
如果应用不进行设置,Glide会全部使用默认配置去创建Glide实例:
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
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(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
2.1、设置Bitmap缓冲池
①setBitmapPool(BitmapPool bitmapPool):Bitmap对象复用缓冲池
//设置Bitmap缓冲池大小32Mb
builder.setBitmapPool(new LruBitmapPool(1024 * 1024 * 32));
开发者可以实现BitmapPool接口,实现自己的Bitmap缓冲池。默认的LruBitmapPool实现已经非常优秀!
/** An interface for a pool that allows users to reuse {@link android.graphics.Bitmap} objects. */
public interface BitmapPool {
...
}
2.2、设置内存缓存
①setMemoryCache(MemoryCache memoryCache):设置内存缓存
builder.setMemoryCache(new LruResourceCache(32 * 1024 * 1024));
同样可以实现MemoryCache接口,自定义内存缓存。不过Glide自带的LruResourceCache已经足够优秀。
/** An interface for adding and removing resources from an in memory cache. */
public interface MemoryCache {
...
}
2.3、配置磁盘缓存
①setDiskCache(DiskCache.Factory diskCacheFactory)
builder.setDiskCache(new DiskLruCacheFactory("image", 32 * 1024 * 1024));
DiskCache.Factory接口定义如下,Glide磁盘缓存默认存储在私有data/data/包名/cache/image_manager_disk_cache目录下,250Mb的缓存。
/** An interface for lazily creating a disk cache. */
interface Factory {
/** 250 MB of cache. */
int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;
String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
...
}
有几个默认的实现,一个是内部存储缓存InternalCacheDiskCacheFactory
//设置128Mb的磁盘缓存大小,目录名仍使用默认的
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, 128 * 1024 * 1024));
另一个是外部磁盘缓存ExternalCacheDiskCacheFactory。不过已经废弃,从Android 11开始建议使用私有目录。
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, 128 * 1024 * 1024));
2.4、配置图片加载选项
①setDefaultRequestOptions(final RequestOptions requestOptions)
RoundedCorners roundedCorners = new RoundedCorners(6);
RequestOptions requestOptions = RequestOptions.bitmapTransform(roundedCorners);
构造一个RequestOptions对象,进行各种设置,加载图片的时候使用这个默认的。不用每次使用Glide加载图片开始with()...的时候单独再设置。
builder.setDefaultRequestOptions(requestOptions
.format(DecodeFormat.PREFER_ARGB_8888)
.diskCacheStrategyOf(DiskCacheStrategy.RESOURCE)
.skipMemoryCache(false)
.encodeQuality(50));
2.5、线程执行器
应用线程过多在性能和耗电上是一个大问题。曾在知乎上看到一篇文章支付宝峰值线程数量高达300多条。Glide内部有自己的线程池实现,如果不设置线程池,Glide会创建自己的线程执行器。
当然最好可以使用应用公用的线程池:
①setDiskCacheExecutor(GlideExecutor service)
②setSourceExecutor(GlideExecutor service)
③setAnimationExecutor(GlideExecutor service)
3、组件注册
自定义好应用的组件如何注册给Glide使之生效呢?
3.1、AndroidManifest中注册
在androidmanifest.xml中的<application />节点下添加<meta-data />,关于Meta Data详见Android meta-data用法。
<application>
<meta-data
android:name="com.quibbler.news.ApplicationGlideModule"
android:value="AppGlideModule" />
</application>
Glide在创建的时候会去加载AndroidManifest中的配置(以后有空分析一下这里解析的原理),isManifestParsingEnabled()方法的默认实现就是true
/**
* Returns {@code true} if Glide should check the AndroidManifest for {@link GlideModule}s.
*
* <p>Implementations should return {@code false} after they and their dependencies have migrated
* to Glide's annotation processor.
*
* <p>Returns {@code true} by default.
*/
public boolean isManifestParsingEnabled() {
return true;
}
3.2、@GlideModule注解
在自定义的AppGlideModule类上加上@GlideModule注解
import com.bumptech.glide.annotation.GlideModule;
@GlideModule
public class ApplicationGlideModule extends AppGlideModule {
...
}
不过别忘了,需要在build.gradle中添加Glide专门的annotationProcessor注解处理器
//Glide
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
同时需要重写isManifestParsingEnabled()方法,返回false,不需要解析AndroidManifest中的配置,有利于提高Glide初始化速度
@Override
public boolean isManifestParsingEnabled() {
return false;
}
4、注意
①自定义的AppGlideModule需要在app/proguard-rules.pro混淆配置文件中配置避免被混淆,以免Glide加载模块出现问题。
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class * extends com.bumptech.glide.module.AppGlideModule {
<init>(...);
}
②APP应用只能定义一个AppGlideModule模块,超过一个会在编译时报错。aar库应用不能实现AppGlideModule,需要使用LibraryGlideModules。
参考资料:
最全Glide 配置、缓存
Glide配置和自定义模块
最简Glide4.8.0配置
Glide缓存配置
Glide中的缓存
Android-Glide配置介绍