Glide源码解析三(注册组件)
转载请标明出处,维权必究: 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源码解析三(注册组件)的更多相关文章
- Flume-ng源码解析之Source组件
如果你还没看过Flume-ng源码解析系列中的启动流程.Channel组件和Sink组件,可以点击下面链接: Flume-ng源码解析之启动流程 Flume-ng源码解析之Channel组件 Flum ...
- Celery 源码解析三: Task 对象的实现
Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...
- Flume-ng源码解析之Sink组件
作为启动流程中第二个启动的组件,我们今天来看看Sink的细节 1 Sink Sink在agent中扮演的角色是消费者,将event输送到特定的位置 首先依然是看代码,由代码我们可以看出Sink是一个接 ...
- Mybatis源码解析(三) —— Mapper代理类的生成
Mybatis源码解析(三) -- Mapper代理类的生成 在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...
- rest-framework源码解析和自定义组件----版本
版本 url中通过GET传参自定义的版本 12345678910111213141516171819202122 from django.http import HttpResponsefrom dj ...
- Flume-ng源码解析之Channel组件
如果还没看过Flume-ng源码解析之启动流程,可以点击Flume-ng源码解析之启动流程 查看 1 接口介绍 组件的分析顺序是按照上一篇中启动顺序来分析的,首先是Channel,然后是Sink,最后 ...
- React的React.createRef()/forwardRef()源码解析(三)
1.refs三种使用用法 1.字符串 1.1 dom节点上使用 获取真实的dom节点 //使用步骤: 1. <input ref="stringRef" /> 2. t ...
- ReactiveCocoa源码解析(三) Signal代码的基本实现
上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...
- ReactiveSwift源码解析(三) Signal代码的基本实现
上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...
- Glide源码解析一,初始化
转载请标明出处:https:////www.cnblogs.com/tangZH/p/12409849.html Glide作为一个强大的图片加载框架,已经被android官方使用,所以,明白Glid ...
随机推荐
- 通过Environment获取属性文件的值,竟然会调用到JNDI服务!!!
一.背景介绍 某应用在压测过程机器cpu使用率超过80%,通过在线诊断工具进行CPU采样生成的火焰图,看到程序中频繁调用environment.getProperty()获取属性值,而其内部调用了Jn ...
- py 学习(c++ to py)
py1: print 2024-01-27 23:18:57 星期六 #这里是注释 # py1 : 基础print总结 ''' aaa 有时候也用三个单引号当注释 但其实是字符串 交互式会输出 ''' ...
- 从零开始配置vim(28)——DAP 配置
首先给大家说一声抱歉,前段时间一直在忙换工作的事,包括但不限于交接.背面试题准备面试.好在最终找到了工作,也顺利入职了.期间也有朋友在催更,在这里我对关注本系列的朋友表示感谢.多的就不说了,我们正式进 ...
- Excel 分列功能 帮助 用户 导入Excel
今天遇见一个客户的 Excel有一列 就是 导入不进去 那列 基本都是 数字 我试了下 写入几个字符 就能导入 不写字符的 就是导入 不进去 龚蓼 告诉我 用分列功能 今天试了下 草 果然可以 ...
- 2021 ASP.NET Core 开发者路线图
GitHub地址:https://github.com/MoienTajik/AspNetCore-Developer-Roadmap/blob/master/ReadMe.zh-Hans.md
- 【.NET】聊聊 IChangeToken 接口
由于两个月的奋战,导致很久没更新了.就是上回老周说的那个产线和机械手搬货的项目,好不容易等到工厂放假了,我就偷偷乐了.当然也过年了,老周先给大伙伴们拜年了,P话不多讲,就祝大家身体健康.生活愉快.其实 ...
- ABC 311
前四题过水 E 枚举正方形的上边界所在行.对于第 \(i\) 行一个没洞的位置 \((i,j)\),我们尝试求出以它为右上角的无洞正方形个数. 结论:设以 \((i,j-1)\) 为右上角的无洞正方形 ...
- Pandas练习
背景介绍 本数据集包括了2015年至2017年我国36个主要一线城市.特区的一些年度数据,包括产值.人口.就业.教育.医疗.经济贸易.房地产投资等方面. 包含文件: 2015年国内主要城市年度数据.c ...
- NC20573 [SDOI2011]染色
题目链接 题目 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如 ...
- NC16122 郊区春游
题目链接 题目 题目描述 今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,路费是Ci.经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑 ...