美文网首页
图片框架 - Glide自定义配置和组件及Registry机制

图片框架 - Glide自定义配置和组件及Registry机制

作者: Stan_Z | 来源:发表于2020-07-17 12:45 被阅读0次

接上篇,代码依然是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

相关文章

网友评论

      本文标题:图片框架 - Glide自定义配置和组件及Registry机制

      本文链接:https://www.haomeiwen.com/subject/fyvuhktx.html