Fresco 源码分析(三) Fresco服务端处理(2) Producer具体实现的内容
我们以mProducerFactory.newNetworkFetchProducer()为例,因为这些创建新的producer的方式类似,区别在于是否有包装的处理器,即如果当前处理器中没有正在处理的数据或者等待处理的数据,便交给包装的处理器来处理
在查看NetworkFetchProducer的源码之前,先来看看producer的接口
Producer的源码
这个接口的功能其实看看类和方法的注释就知道了,就是用于产生结果的,这个使用与网络数据的获取,磁盘缓存,内存缓存,解码,编码和图片的变性处理等等
这种设计模式的特点的好处在于,将图片整体处理的逻辑打散为不同的区块处理,这样实现了模块化
/**
* Building block for image processing in the image pipeline.
*
* <p> Execution of image request consists of multiple different tasks such as network fetch,
* disk caching, memory caching, decoding, applying transformations etc. Producer<T> represents
* single task whose result is an instance of T. Breaking entire request into sequence of
* Producers allows us to construct different requests while reusing the same blocks.
*
* <p> Producer supports multiple values and streaming.
*
* @param <T>
*/
public interface Producer<T> {
/**
* Start producing results for given context. Provided consumer is notified whenever progress is
* made (new value is ready or error occurs).
* @param consumer
* @param context
*/
void produceResults(Consumer<T> consumer, ProducerContext context);
}
在继续分析Producer的处理逻辑之前,我们先把遗留的Q5问题解决: 即ProducerSequenceFactory.newBitmapCacheGetToDecodeSequence()的源码分析续
再来回顾一下:
ProducerSequenceFactory.newBitmapCacheGetToDecodeSequence()的源码
上篇已经提到了根据网络的请求的producer,然后生成了解码的producer,在根据这个解码的producer,生成newBitmapCacheGetToBitmapCacheSequence
/**
* Same as {@code newBitmapCacheGetToBitmapCacheSequence} but with an extra DecodeProducer.
* @param nextProducer next producer in the sequence after decode
* @return bitmap cache get to decode sequence
*/
private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToDecodeSequence(
Producer<EncodedImage> nextProducer) {
DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(nextProducer);
return newBitmapCacheGetToBitmapCacheSequence(decodeProducer);
}
那么下面需要关注的就是newBitmapCacheGetToBitmapCacheSequence()的过程
** ProducerSequenceFactory.newBitmapCacheGetToBitmapCacheSequence()的源码 **
这段逻辑其实就是ImagePipeline最先处理逻辑的倒叙,就是从bitmapCacheCacheGetProducer到HandlerOff的处理,BitmapCache的生成的倒叙
将包装处理类一步步传递给上层处理器
/**
* Bitmap cache get -> thread hand off -> multiplex -> bitmap cache
* @param nextProducer next producer in the sequence after bitmap cache
* @return bitmap cache get to bitmap cache sequence
*/
private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToBitmapCacheSequence(
Producer<CloseableReference<CloseableImage>> nextProducer) {
BitmapMemoryCacheProducer bitmapMemoryCacheProducer =
mProducerFactory.newBitmapMemoryCacheProducer(nextProducer);
BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer =
mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);
ThreadHandoffProducer<CloseableReference<CloseableImage>> threadHandoffProducer =
mProducerFactory.newBackgroundThreadHandoffProducer(bitmapKeyMultiplexProducer);
return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);
}
由于初始化过程的类似,我们直接跳到这个方法最后的new过程,newBitmapMemoryCacheGetProducer()方法
直接看这个过程,发现
public BitmapMemoryCacheGetProducer newBitmapMemoryCacheGetProducer(
Producer<CloseableReference<CloseableImage>> nextProducer) {
return new BitmapMemoryCacheGetProducer(mBitmapMemoryCache, mCacheKeyFactory, nextProducer);
}
public BitmapMemoryCacheGetProducer(
MemoryCache<CacheKey, CloseableImage> memoryCache,
CacheKeyFactory cacheKeyFactory,
Producer<CloseableReference<CloseableImage>> nextProducer) {
super(memoryCache, cacheKeyFactory, nextProducer);
}
暂且先看到这里,做个标记,由于中间处理的逻辑大体相似,所以我们分析producer的一头一尾即可,知道中间的处理流程,一个是处理的头部BitmapMemoryCacheGetProducer, 另外一个是尾部NetworkFetchProducer,但是如果在深入分析,我们就会陷入细节,先将ImagePipeline的整体分析完后,我们再分析这里,标记为Q6:分析BitmapMemoryCacheGetProducer和NetworkFetchProducer
4.3.1.2 ImagePipeline.fetchDecodedImage() 源码分支2的处理
由于中间已经分析了producer的很多知识,所以我们先回顾一下ImagePipeline的fetchDecodedImage()的过程
ImagePipeline.fetchDecodedImage() 源码
1.获取到producer
2.根据生成的producer提交请求
/**
* Submits a request for execution and returns a DataSource representing the pending decoded
* image(s).
*
* <p>The returned DataSource must be closed once the client has finished with it.
* @param imageRequest the request to submit
* @return a DataSource representing the pending decoded image(s)
*/
public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext) {
try {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
分支1已经在4.3.1.1中分析,接下来分析producer的提交请求
ImagePipeline.submitFetchRequest()源码
计算出当前图片请求的最低的请求级别
创建一个SettableProducerContext
根据创建的settableProducerContext,再将利用Producer和DataSource中间的适配器,创建了一个DataSource(需要理解的核心部分)
private <T> DataSource<CloseableReference<T>> submitFetchRequest(
Producer<CloseableReference<T>> producerSequence,
ImageRequest imageRequest,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
Object callerContext) {
try {
ImageRequest.RequestLevel lowestPermittedRequestLevel =
ImageRequest.RequestLevel.getMax(
imageRequest.getLowestPermittedRequestLevel(),
lowestPermittedRequestLevelOnSubmit);
SettableProducerContext settableProducerContext = new SettableProducerContext(
imageRequest,
generateUniqueFutureId(),
mRequestListener,
callerContext,
lowestPermittedRequestLevel,
/* isPrefetch */ false,
imageRequest.getProgressiveRenderingEnabled() ||
!UriUtil.isNetworkUri(imageRequest.getSourceUri()),
imageRequest.getPriority());
return CloseableProducerToDataSourceAdapter.create(
producerSequence,
settableProducerContext,
mRequestListener);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
上面的逻辑看起来很简单,包涵的知识挺多的,咱们一个一个说
- 计算出当前图片请求的最低的请求级别
根据前一个方法的调用的参数,得知是与最低级别的ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE,所以在提交请求时最低级别就是我们在请求中设置的级别
2. 创建一个SettableProducerContext
ProducerContext也是请求信息的一个上下文,这里包含了所有在producer处理过程中需要得知的信息,例如图片的请求信息,请求的优先级,请求的id,是否要预处理等等.
- 根据创建的settableProducerContext,再将利用Producer和DataSource中间的适配器,创建了一个DataSource(需要理解的核心部分),并且做了返回
过程1和过程2比较简单,这个可以自己看看哈,大概作用就是上面描述的,我们来看看过程3
CloseableProducerToDataSourceAdapter.create(
producerSequence,
settableProducerContext,
mRequestListener);
创建了一个可关闭的生产者到数据源的适配器,就是讲生产者和数据源进行了关联,这个类似于连接器的一个作用,其实发送请求的核心逻辑位于这个地方,因为Producer只是负责生产数据,需要有对应的Consumer来消费数据,数据源是DataSource,那么消费的数据如何得到这个通知呢?这个其实就是客户端的DataSubscriber(剧透一下),其实数据适配器就是做了这样的一个逻辑.算是剧透了,下面我们开始一步一步分析这个过程
安卓源码分析群: Android源码分析QQ1群号:164812238
安卓源码分析群: Android源码分析QQ1群号:164812238
Fresco 源码分析(三) Fresco服务端处理(2) Producer具体实现的内容的更多相关文章
- Fresco 源码分析(三) Fresco服务端处理(1) ImagePipeline为何物
4.3 服务端的处理 备注: 因为是分析,而不是设计,所以很多知识我们类似于插叙的方式叙述,就是用到了哪个知识点,我们再提及相关的知识点,如果分析到了最后,我想想是不是应该将这个架构按照设计的方式,重 ...
- Fresco 源码分析(三) Fresco服务端处理(3) DataSource到Producer的适配器逻辑以及BitmapMemoryCacheProducer处理的逻辑
4.3.1.2.1 Producer和DataSource之间适配器处理的逻辑 还是从程序的入口开始说吧 CloseableProducerToDataSourceAdapter.create() 源 ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通
4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题
4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(2) Fresco.initializeDrawee()分析 续
4.2.1.2 Fresco.initializeDrawee()的过程 续 继续上篇博客的分析Fresco.initializeDrawee() sDraweeControllerBuilderSu ...
- 【Netty源码分析】Netty服务端bind端口过程
这一篇博客我们介绍一下Netty服务端绑定端口的过程,我们通过跟踪代码一直到NIO原生绑定端口的操作. 绑定端口操作 ChannelFuture future = serverBootstrap.bi ...
- Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析
4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用 DraweeHierachy (I) --| SettableDraweeHierarchy (I) ------| Gen ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- angular源码分析:$compile服务——directive他妈
一.directive的注册 1.我们知道,我们可以通过类似下面的代码定义一个指令(directive). var myModule = angular.module(...); myModule.d ...
随机推荐
- 在myeclipse10.7.1中写代码有很多红x
代码没问题,但是很多代码前都有红x.在doc中执行都没有问题 jdk版本不对应 //第一步:菜单栏Window--Preferences--Java--Installed JREs--右边Add ...
- python scrapy 获取华为应用市场APP评论数据
scrapy入门 四步: 1. 创建一个新的Scrapy Project 2. 定义你需要从网页中提取的元素Item 3. 实现一个Spider类,通过接口完成爬取URL和提取Item的功能 4. 实 ...
- MVC4笔记 Area区域
mvc4.0新增的area区域机制,可以协助你在架构较为大型的项目,让独立性较高的部分功能独立成一个MVC子网站,以降低网站与网站之间的耦合性,也可以通过area的切割,让多人同时开发同一个项目时候, ...
- c++ std::string.c_str()
语法: const char *c_str();搜索 c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同. 这是为了与c语言兼容,在c语言中没有string类型,故必须通过 ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- JQ系列:css操作
JQ中的 .css()有三种使用方法: $('#p').css('width'); 取得ID为p的样式属性的width值;等同 return width $('#p').css('width','10 ...
- acdream.Bet(数学推导)
Bet Time Limit:1000MS Memory Limit:64000KB 64bit IO Format:%lld & %llu Submit Status Pra ...
- 如何让Ubuntu系统支持WebP图片格式
本文主要向大家介绍如何让 Ubuntu 系统支持查看 WebP 图片格式,以及如何将 WebP 转为 JPEG 或 PNG 图片格式的方法. 什么是WebP图片 Google开发并推出 WebP 图片 ...
- Nginx安装与配置文件解析
导读 Nginx是一款开放源代码的高性能HTTP服务器和反向代理服务器,同时支持IMAP/POP3代理服务,是一款自由的软件,同时也是运维工程师必会的一种服务器,下面我就简单的说一下Nginx服务器的 ...
- 滚动光效shader
Shader "Custom/LightMove" { Properties { _MainTex ("Base (RGB)", 2D) = "whi ...