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 ...
随机推荐
- vscode搜索框不见了如何显示
- Go复合类型之数组类型
Go复合类型之数组 @ 目录 Go复合类型之数组 一.数组(Array)介绍 1.1 基本介绍 1.2 数组的特点 二.数组的声明与初始化 2.1 数组声明 2.2 常见的数据类型声明方法 2.3 数 ...
- windowsbat删除命令
widnwosbat命令 DEL /F /A /Q \?%1 用于删除指定路径下的文件,参数含义如下: /F: Force delete,即强制删除: /A: 用于指定文件属性,A代表存档,D代表目录 ...
- Rocketmq学习4——Broker消息持久化原理源码浅析
一丶前言 在<Rocketmq学习3--消息发送原理源码浅析>中,我们学习了消息发送的要点: 本地缓存+rpc 请求namesever + 定时刷新,topic路由信息 负载均衡的选择一个 ...
- 微信小程序-页面生命周期
官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page-life-cycle.html
- 【主流技术】实战之 Spring Boot 中集成微信支付(小程序)
前言 微信支付是企业级项目中经常使用到的功能,作为后端开发人员,完整地掌握该技术是十分有必要的. 以下是经过真实商业项目实践的集成步骤,包括注册流程.调用过程.代码demo(经过脱敏)等,希望我的分享 ...
- 群联预告满血PCIe 5.0 SSD主控:飙上14.7GB/s
群联电子将在CES 2024上展示两款新的PCIe 5.0 SSD主控方案,一个定位旗舰,一个面向主流. PCIe 5.0 SSD诞生已经差不多一年了,但是受限于群联E26主控的先天不足,以及闪存技术 ...
- Oracle配置DCD避免会话被防火墙强制断开
今天有客户反馈应用测试连接Oracle数据库的会话半小时左右未做操作就会被中断,报错ORA-3113,询问数据库是否有这样的超时设置,能否取消掉这个限制? 登上环境查看监听日志发现连接的IP和数据库I ...
- Adoquery.Refresh 慎用。。。。非常严重,会带来各种问题。
adoquery.refresh 各种问题,根本启不到刷新的作用.完全不刷新的节奏. 修改成已经打印后,如果用adoquery.refresh的话,这两个订单 并不会被刷新掉,惨吧......
- 2023牛客暑期多校训练营6 ABCEG
比赛链接 A 题解 方法一 知识点:并查集,树形dp,背包dp. 因为需要路径中的最大值,因此考虑按边权从小到大加入图中,保证通过这条边产生贡献的点对已经全部出现. 在加边的同时进行树上背包,答案存在 ...