转载请标明出处,维权必究: 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. 通过Environment获取属性文件的值,竟然会调用到JNDI服务!!!

    一.背景介绍 某应用在压测过程机器cpu使用率超过80%,通过在线诊断工具进行CPU采样生成的火焰图,看到程序中频繁调用environment.getProperty()获取属性值,而其内部调用了Jn ...

  2. py 学习(c++ to py)

    py1: print 2024-01-27 23:18:57 星期六 #这里是注释 # py1 : 基础print总结 ''' aaa 有时候也用三个单引号当注释 但其实是字符串 交互式会输出 ''' ...

  3. 从零开始配置vim(28)——DAP 配置

    首先给大家说一声抱歉,前段时间一直在忙换工作的事,包括但不限于交接.背面试题准备面试.好在最终找到了工作,也顺利入职了.期间也有朋友在催更,在这里我对关注本系列的朋友表示感谢.多的就不说了,我们正式进 ...

  4. Excel 分列功能 帮助 用户 导入Excel

    今天遇见一个客户的 Excel有一列 就是 导入不进去  那列 基本都是 数字 我试了下  写入几个字符 就能导入  不写字符的 就是导入 不进去 龚蓼 告诉我 用分列功能 今天试了下  草 果然可以 ...

  5. 2021 ASP.NET Core 开发者路线图

    GitHub地址:https://github.com/MoienTajik/AspNetCore-Developer-Roadmap/blob/master/ReadMe.zh-Hans.md

  6. 【.NET】聊聊 IChangeToken 接口

    由于两个月的奋战,导致很久没更新了.就是上回老周说的那个产线和机械手搬货的项目,好不容易等到工厂放假了,我就偷偷乐了.当然也过年了,老周先给大伙伴们拜年了,P话不多讲,就祝大家身体健康.生活愉快.其实 ...

  7. ABC 311

    前四题过水 E 枚举正方形的上边界所在行.对于第 \(i\) 行一个没洞的位置 \((i,j)\),我们尝试求出以它为右上角的无洞正方形个数. 结论:设以 \((i,j-1)\) 为右上角的无洞正方形 ...

  8. Pandas练习

    背景介绍 本数据集包括了2015年至2017年我国36个主要一线城市.特区的一些年度数据,包括产值.人口.就业.教育.医疗.经济贸易.房地产投资等方面. 包含文件: 2015年国内主要城市年度数据.c ...

  9. NC20573 [SDOI2011]染色

    题目链接 题目 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如 ...

  10. NC16122 郊区春游

    题目链接 题目 题目描述 今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,路费是Ci.经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑 ...