转载请标明出处,维权必究: https://www.cnblogs.com/tangZH/p/12900387.html

本文基于Glide 4.11.0

这里说的注册便是Glide初始化过程中,对解码器,编码器等的注册。

具体初始化过程可以看http://77blogs.com/?p=269

本文主要讲初始化过程中,注册到底做了什么,注册的这些又存储在哪里。

比如源码中的下面代码:

registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
/* Bitmaps */
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder);

可以在glide初始化过程中看到执行注册的是Register对象,我们可以进去看看。

private final ModelLoaderRegistry modelLoaderRegistry;
private final EncoderRegistry encoderRegistry;
private final ResourceDecoderRegistry decoderRegistry;
private final ResourceEncoderRegistry resourceEncoderRegistry;
private final DataRewinderRegistry dataRewinderRegistry;
private final TranscoderRegistry transcoderRegistry;
private final ImageHeaderParserRegistry imageHeaderParserRegistry;

可以看到很多个相关的类。

ModelLoaderRegistry :注册模型加载器相关

EncoderRegistry:注册编码器相关

ResourceDecoderRegistry:注册资源解码器相关

ResourceEncoderRegistry :注册资源编码器相关

DataRewinderRegistry:数据类型对应的资源数据相关

TranscoderRegistry:注册转码器相关

ImageHeaderParserRegistry :解析图片文件头的解析器相关

一、模型加载器

如源码中:

registry
.append(int.class, InputStream.class, resourceLoaderStreamFactory)

将int类型加载为InputStream类型,加载器为resourceLoaderStreamFactory,比如我们加载图片的时候传递给glide的是一个资源id,那么glide会运用resourceLoaderStreamFactory

模型加载器将该资源id加载为InputStream,之后再是解码的过程。

进去发现它会调用:

modelLoaderRegistry.append(modelClass, dataClass, factory);

接着在ModelLoaderRegistry里面会调用:

multiModelLoaderFactory.append(modelClass, dataClass, factory);

追溯代码最终到这里:

  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

public Entry(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
this.modelClass = modelClass;
this.dataClass = dataClass;
this.factory = factory;
}

然后存放于一个list里面,这个list在multiModelLoaderFactory里。

private final List<Entry<?, ?>> entries = new ArrayList<>();

二、编码器

如源码中的:

registry
.append(ByteBuffer.class, new ByteBufferEncoder())

将ByteBuffer类型数据编码为一个文件存放下来,编码器为ByteBufferEncoder

进去里面可以发现他调用了EncoderRegistry的append方法,然后构造一个Entry,存放在EncoderRegistry的一个集合里面:

private final List<Entry<?>> encoders = new ArrayList<>();

三、资源解码器

如源码中:

registry
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)

将ByteBuffer类型解码为Bitmap类型,解码器为byteBufferBitmapDecoder

而Registry.BUCKET_BITMAP代表的是一种类型,因为每种类型可以对应多种解码器,如:

.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder);

我们最终来到这个方法:

public synchronized <T, R> void append(
@NonNull String bucket,
@NonNull ResourceDecoder<T, R> decoder,
@NonNull Class<T> dataClass,
@NonNull Class<R> resourceClass) {
getOrAddEntryList(bucket).add(new Entry<>(dataClass, resourceClass, decoder));
}

getOrAddEntryList返回的是一个List<Entry<?, ?>>类型,里面存放着构造好的Entry实体类。这个List其实存放的是同样类型的解码器,比如都是Registry.BUCKET_BITMAP类型的,而这个整个List存放在一个map里面,key就是Registry.BUCKET_BITMAP。

private final Map<String, List<Entry<?, ?>>> decoders = new HashMap<>();

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;
}

getOrAddEntryList方法里面,通过bucketPriorityList判断是否已经有了一个这个类型的list,有的话直接从map获取该list,然后将注册的放进去。

四、资源编码器

如源码中:

如:

.append(GifDrawable.class, new GifDrawableEncoder())

将GifDrawable资源类型进行编码,编码器为:GifDrawableEncoder,GifDrawableEncoder里面主要是将gif数据保存为文件,对gif进行磁盘缓存的时候便需要用到这个编码器。

存储的过程与之前的类似,存在list中。

五、转码器

如源码中的:

register.register(Bitmap.class, BitmapDrawable.class, new BitmapDrawableTranscoder(resources))

将Bitmap转化为BitmapDrawable,转码器为BitmapDrawableTranscoder

存储过程类似。

六、ImageHeaderParserRegistry 

如源码中的:

registry.register(new DefaultImageHeaderParser());

默认的image文件头的解析器,可以由这个解析器判断图片类型,这也是用同样的代码能够加载动图与静图的原因。

存储过程类似。

至于DataRewinderRegistry 还未细看,后面再来补充,后面也会继续更新Glide相关的源码解析。

Glide源码解析三(注册组件)的更多相关文章

  1. Flume-ng源码解析之Source组件

    如果你还没看过Flume-ng源码解析系列中的启动流程.Channel组件和Sink组件,可以点击下面链接: Flume-ng源码解析之启动流程 Flume-ng源码解析之Channel组件 Flum ...

  2. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

  3. Flume-ng源码解析之Sink组件

    作为启动流程中第二个启动的组件,我们今天来看看Sink的细节 1 Sink Sink在agent中扮演的角色是消费者,将event输送到特定的位置 首先依然是看代码,由代码我们可以看出Sink是一个接 ...

  4. Mybatis源码解析(三) —— Mapper代理类的生成

    Mybatis源码解析(三) -- Mapper代理类的生成   在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...

  5. rest-framework源码解析和自定义组件----版本

    版本 url中通过GET传参自定义的版本 12345678910111213141516171819202122 from django.http import HttpResponsefrom dj ...

  6. Flume-ng源码解析之Channel组件

    如果还没看过Flume-ng源码解析之启动流程,可以点击Flume-ng源码解析之启动流程 查看 1 接口介绍 组件的分析顺序是按照上一篇中启动顺序来分析的,首先是Channel,然后是Sink,最后 ...

  7. React的React.createRef()/forwardRef()源码解析(三)

    1.refs三种使用用法 1.字符串 1.1 dom节点上使用 获取真实的dom节点 //使用步骤: 1. <input ref="stringRef" /> 2. t ...

  8. ReactiveCocoa源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  9. ReactiveSwift源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  10. Glide源码解析一,初始化

    转载请标明出处:https:////www.cnblogs.com/tangZH/p/12409849.html Glide作为一个强大的图片加载框架,已经被android官方使用,所以,明白Glid ...

随机推荐

  1. TypeScript接口的讲解-强制约束-可选属性-任意多个属性-只读属性

    接口 接口:可以描述类的一部分抽象行为, 也可以描述数据的结构形状 接口一般首字母大写, 接口中 可以定义为 强制约束 可选属性 只读属性 任意属性 # 强制约束 // 定义接口 interface ...

  2. 【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  3. 【JS 逆向百例】层层嵌套!某加速商城 RSA 加密

    声明 本文章中所有内容仅供学习交流,敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:某加速商城登录接口 ...

  4. C/C++ Npcap包实现ARP欺骗

    npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,唯一的 ...

  5. SpringCloud-06-Consul注册中心

    Consul Server Consul 是由 HashiCorp 基于 Go 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件. 用于实现分布式系统的服务发现与配置. 使用起来也较 ...

  6. python截取字符串(字符串切片)

    python中使用[]来截取字符串,语法: 字符串[起始位置:结束位置] 一.起始位置:结束位置 先看几个例子: s = 'python' print(s) #输出 python 直接输出字符串 #从 ...

  7. [奶奶看了都会]ChatGPT接入企业微信成为聊天机器人

    1.聊天效果 上次给大家讲了ChatGPT接入个人微信的方法,但是个人微信容易被封号.这次就教大家接入企业微信,不会再被封号哦~ 话不多说,直接看机器人的聊天效果.基本能实现ChatGPT的聊天效果了 ...

  8. NC19995 [HAOI2015]树上操作

    题目链接 题目 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  9. Python 中获取文件名

    Python 获取文件名import osimport sys # ①获取当前文件名os.path.basename(__file__)# ②获取程序启动文件名os.path.basename(sys ...

  10. python中矩阵合并、拼接、组合

    1 numpy数组 1.1 append() import numpy as np a=np.array([[1,3],[5,7]]) b=np.array([[2,4],[6,8]]) c=np.a ...