接上篇,代码依然是4.11.0版本。
一、自定义配置和组件
1.1 Glide如何实现自定义配置和组件
/**
* GlideModule注册方式:
* 1)在application中加入:
* <meta-data
* android:name="xxx.xxx.xxx.glide.configure.CustomGlideMoudle"
* android:value="GlideModule" />
* 2)@GlideModule注解
*/
@GlideModule
public final class CustomAppGlideModule extends AppGlideModule {
//自定义配置
@Override
public void applyOptions(Context context, GlideBuilder builder) {
这里主要配置GlideBuilder
常用设置项:
setMemoryCache() //用于配置Glide的内存缓存策略,默认配置是LruResourceCache。
setBitmapPool()//用于配置Glide的Bitmap缓存池,默认配置是LruBitmapPool。
setDiskCache()//用于配置Glide的硬盘缓存策略,默认配置是InternalCacheDiskCacheFactory。
setDiskCacheService()//用于配置Glide读取缓存中图片的异步执行器,默认配置是FifoPriorityThreadPoolExecutor,也就是先入先出原则。
setResizeService()//用于配置Glide读取非缓存中图片的异步执行器,默认配置也是FifoPriorityThreadPoolExecutor。
setDecodeFormat()//用于配置Glide加载图片的解码模式,默认配置是RGB_565。
}
/**
* Glide V4 版本,禁用清单解析选项
*/
@Override
public boolean isManifestParsingEnabled() {
return false;
}
//自定义组件
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
这里通过Registry对组件进行注册
append 尾部追加
prepend 头部插入
register 注册、相当于append
replace 替换掉相同条件的模块
}
}
1.2 自定义配置和组件的调用流程
Glide本身是单例,最初的初始化:
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
看 getAnnotationGeneratedGlideModules(context.getApplicationContext()):
private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules(Context context) {
GeneratedAppGlideModule result = null;
try {
Class<GeneratedAppGlideModule> clazz =
(Class<GeneratedAppGlideModule>)
Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl");
result = clazz.getDeclaredConstructor(Context.class).newInstance(context.getApplicationContext());
} catch (ClassNotFoundException e) {
...
}
return result;
}
它本身就是通过反射来使用com.bumptech.glide.GeneratedAppGlideModuleImpl 这个类。找下这个类:
很明显是由APT生成的,既然是APT,那就去找对应生成文件的Porcessor
对应的Glide引库为:annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
com.bumptech.glide.GeneratedAppGlideModuleImpl生成的主Processor在:
@AutoService(Processor.class)
public final class GlideAnnotationProcessor extends AbstractProcessor {
static final boolean DEBUG = false;
private ProcessorUtil processorUtil;
private LibraryModuleProcessor libraryModuleProcessor;
private AppModuleProcessor appModuleProcessor;
private boolean isGeneratedAppGlideModuleWritten;
private ExtensionProcessor extensionProcessor;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
processorUtil = new ProcessorUtil(processingEnvironment);
IndexerGenerator indexerGenerator = new IndexerGenerator(processorUtil);
libraryModuleProcessor = new LibraryModuleProcessor(processorUtil, indexerGenerator);
appModuleProcessor = new AppModuleProcessor(processingEnvironment, processorUtil);
extensionProcessor =
new ExtensionProcessor(processingEnvironment, processorUtil, indexerGenerator);
}
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> result = new HashSet<>();
result.addAll(libraryModuleProcessor.getSupportedAnnotationTypes());
result.addAll(extensionProcessor.getSupportedAnnotationTypes());
return result;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment env) {
processorUtil.process();
boolean newModulesWritten = libraryModuleProcessor.processModules(env);
boolean newExtensionWritten = extensionProcessor.processExtensions(env);
appModuleProcessor.processModules(set, env);
if (newExtensionWritten || newModulesWritten) {
if (isGeneratedAppGlideModuleWritten) {
throw new IllegalStateException("Cannot process annotations after writing AppGlideModule");
}
return true;
}
if (!isGeneratedAppGlideModuleWritten) {
isGeneratedAppGlideModuleWritten = appModuleProcessor.maybeWriteAppModule();
}
return true;
}
}
不了解编译时注解的可以参考之前的文章:Java基础(二)-注解
运行时注解简而言之就是在编译器生成一个类文件,类的内容通过javapoet组装出来。这个不是本文的重点,点到为止,那么来看看
生成后的内容:
@SuppressWarnings("deprecation")
final class GeneratedAppGlideModuleImpl extends GeneratedAppGlideModule {
private final CustomAppGlideModule appGlideModule;
GeneratedAppGlideModuleImpl() {
//CustomAppGlideModule 实现了AppGlideModule,并且由@GlideModule方式注册
appGlideModule = new CustomAppGlideModule();
if (Log.isLoggable("Glide", Log.DEBUG)) {
Log.d("Glide", "Discovered AppGlideModule from annotation: com.mgtv.lib.tv.imageloader.CustomAppGlideModule");
Log.d("Glide", "Discovered LibraryGlideModule from annotation: com.bumptech.glide.integration.webp.WebpGlideLibraryModule");
}
}
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
appGlideModule.applyOptions(context, builder);
}
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide,
@NonNull Registry registry) {
//WebpGlideLibraryModule 实现了LibraryGlideModule,并且由@GlideModule方式注册
new WebpGlideLibraryModule().registerComponents(context, glide, registry);
appGlideModule.registerComponents(context, glide, registry);
}
@Override
public boolean isManifestParsingEnabled() {
return appGlideModule.isManifestParsingEnabled();
}
@Override
@NonNull
public Set<Class<?>> getExcludedModuleClasses() {
return Collections.emptySet();
}
@Override
@NonNull
GeneratedRequestManagerFactory getRequestManagerFactory() {
return new GeneratedRequestManagerFactory();
}
}
这里总结下本地的配置在GeneratedAppGlideModuleImpl生成的规则:
-
AppGlideModule 只能实现1个,但是LibraryGlideModule可以实现多个。LibraryGlideModule只有registerComponents自定义组件功能,而AppGlideModule在LibraryGlideModule基础上增加了applyOptions自定义配置功能
-
如果是@GlideModule注册,则会直接在GeneratedAppGlideModuleImpl创建对象,并执行相应方法,如果是manifest注册,则会到Glide初始化流程去进行处理。
好的,现在Glide反射的GeneratedAppGlideModuleImpl以及了解了,那么接下来看看使用:
Glide.java
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
接着看 checkAndInitializeGlide(context, annotationGeneratedModule),经过层层调用,最终:
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Context applicationContext = context.getApplicationContext();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
//移除需要排除的GlideModule
...
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
//针对manifest 和 注解两种注册方式分别调用其applyOptions和registerComponents
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//通过GlideBuilder做一系列初始化工作
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
module.registerComponents(applicationContext, glide, glide.registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: "
+ module.getClass().getName(),
e);
}
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
这里针对manifest 和 注解两种注册方式分别调用其applyOptions和registerComponents来触发自定义配置和组件。
二、Registry机制
前面介绍了,registerComponents中是通过Registry对组件进行注册的,这里简单了解下Registry机制。
Registry初始化时机是在Glide的构造方法中,并且在那会添加一批默认的组件。
Registry本身的意义是组件根据功能进行灵活挂载。它只是作为一个入口类,具体功能会由如下具体Registry来处理:
- ModelLoaderRegistry 注册ModelLoader
- EncoderRegistry 注册Encoder
- ResourceDecoderRegistry 注册ResourceDecoder
- ResourceEncoderRegistry 注册ResourceEncoder
- DataRewinderRegistry 注册DataRewinder
- TranscoderRegistry 注册ResourceTranscoder
- ImageHeaderParserRegistry 注册ImageHeaderParser
相关类介绍:
- ModelLoader 由ModelLoaderFactory创建,作用是经由内部类LoadData将复杂数据模型转通过DataFetcher转换成需要的DataClass。
- Encoder 将通用T持久化到本地cache
- ResourceDecoder 解码Resource
- ResourceEncoder 将Bitmap和对应Drawable持久化到本地cache
- DataRewinder 对流进行重置数据起点
- ResourceTranscoder 对Resource进行转换
- ImageHeaderParser 图片头解析
以替换网络请求OKHTTP为例来介绍:
Registry.java
registry.replace(
GlideUrl.class, //Class<Model> modelClass ,GlideUrl对应的是一种Key,表示http/https url的字符串包装器。
InputStream.class, //Class<Data> dataClass, 数据类型
new OkHttpUrlLoader.Factory() //ModelLoaderFactory<? extends Model, ? extends Data> factory) 初始化了OkHttpClient
modelLoaderRegistry.replace(modelClass, dataClass, factory);
);
ModelLoaderRegistry.java
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
tearDown(multiModelLoaderFactory.replace(modelClass, dataClass, factory));//tearDown在OkHttpUrlLoader没做逻辑
cache.clear();
}
MultiModelLoaderFactory
@NonNull
synchronized <Model, Data> List<ModelLoaderFactory<? extends Model, ? extends Data>> replace(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
List<ModelLoaderFactory<? extends Model, ? extends Data>> removed =
remove(modelClass, dataClass);//删除以前的组件
append(modelClass, dataClass, factory);//添加当前新的组件
return removed;
}
synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
add(modelClass, dataClass, factory, /*append=*/ true);
}
private final List<Entry<?, ?>> entries = new ArrayList<>();
private <Model, Data> void add(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory,
boolean append) {
Entry<Model, Data> entry = new Entry<>(modelClass, dataClass, factory);
entries.add(append ? entries.size() : 0, entry);
}
最终以Entry的形式添加到MultiModelLoaderFactory的ArrayList中。
再举个例子:
registry..prepend(
Registry.BUCKET_BITMAP, //String bucket : bitmap
InputStream.class,//Class<Data> dataClass
Bitmap.class,//Class<TResource> resourceClass
new StreamAnimatedBitmapDecoder(bitmapDecoder) //ResourceDecoder<Data, TResource> decoder
decoderRegistry.prepend(bucket, decoder, dataClass, resourceClass);//ResourceDecoderRegistry
);
最大区别是最后传入的是个ResourceDecoder。
ResourceDecoderRegistry.java
private final List<String> bucketPriorityList = new ArrayList<>();
private final Map<String, List<Entry<?, ?>>> decoders = new HashMap<>();
public synchronized <T, R> void prepend(
@NonNull String bucket,
@NonNull ResourceDecoder<T, R> decoder,
@NonNull Class<T> dataClass,
@NonNull Class<R> resourceClass) {
getOrAddEntryList(bucket).add(0, new Entry<>(dataClass, resourceClass, decoder));
}
@NonNull
private synchronized List<Entry<?, ?>> getOrAddEntryList(@NonNull String bucket) {
if (!bucketPriorityList.contains(bucket)) {
// Add this unspecified bucket as a low priority bucket.
bucketPriorityList.add(bucket);
}
List<Entry<?, ?>> entries = decoders.get(bucket);
if (entries == null) {
entries = new ArrayList<>();
decoders.put(bucket, entries);
}
return entries;
}
最终以Entry的形式保留在ResourceDecoderRegistry的map中。
后续是如何用的,参考后面的文章。
参考:
https://blog.csdn.net/weixin_34368949/article/details/88032953
网友评论