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 ...
随机推荐
- TypeScript接口的讲解-强制约束-可选属性-任意多个属性-只读属性
接口 接口:可以描述类的一部分抽象行为, 也可以描述数据的结构形状 接口一般首字母大写, 接口中 可以定义为 强制约束 可选属性 只读属性 任意属性 # 强制约束 // 定义接口 interface ...
- 【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...
- 【JS 逆向百例】层层嵌套!某加速商城 RSA 加密
声明 本文章中所有内容仅供学习交流,敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:某加速商城登录接口 ...
- C/C++ Npcap包实现ARP欺骗
npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,唯一的 ...
- SpringCloud-06-Consul注册中心
Consul Server Consul 是由 HashiCorp 基于 Go 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件. 用于实现分布式系统的服务发现与配置. 使用起来也较 ...
- python截取字符串(字符串切片)
python中使用[]来截取字符串,语法: 字符串[起始位置:结束位置] 一.起始位置:结束位置 先看几个例子: s = 'python' print(s) #输出 python 直接输出字符串 #从 ...
- [奶奶看了都会]ChatGPT接入企业微信成为聊天机器人
1.聊天效果 上次给大家讲了ChatGPT接入个人微信的方法,但是个人微信容易被封号.这次就教大家接入企业微信,不会再被封号哦~ 话不多说,直接看机器人的聊天效果.基本能实现ChatGPT的聊天效果了 ...
- NC19995 [HAOI2015]树上操作
题目链接 题目 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- Python 中获取文件名
Python 获取文件名import osimport sys # ①获取当前文件名os.path.basename(__file__)# ②获取程序启动文件名os.path.basename(sys ...
- 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 ...