4.3.1.2.1 Producer和DataSource之间适配器处理的逻辑

还是从程序的入口开始说吧

CloseableProducerToDataSourceAdapter.create() 源码

此处看到无非是创建了一个新的数据适配器而已CloseableProducerToDataSourceAdapter

  public static <T> DataSource<CloseableReference<T>> create(
Producer<CloseableReference<T>> producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
return new CloseableProducerToDataSourceAdapter<T>(
producer, settableProducerContext, listener);
}

继续跟踪

CloseableProducerToDataSourceAdapter构造的过程

看到这里,发现并没有做什么特殊的操作,只是调用了父类构造而已

  private CloseableProducerToDataSourceAdapter(
Producer<CloseableReference<T>> producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
super(producer, settableProducerContext, listener);
}

AbstractProducerToDataSourceAdapter构造的过程

寻找了这么久,终于找到了核心的逻辑,在这里,

  1. 初始化Adapter的参数
  2. 通知外界的mRequestListener已经开始了请求
  3. 生产者producer开始了生产数据(核心逻辑)

    protected AbstractProducerToDataSourceAdapter(

    Producer producer,

    SettableProducerContext settableProducerContext,

    RequestListener requestListener) {

    mSettableProducerContext = settableProducerContext;

    mRequestListener = requestListener;

    mRequestListener.onRequestStart(

    settableProducerContext.getImageRequest(),

    mSettableProducerContext.getCallerContext(),

    mSettableProducerContext.getId(),

    mSettableProducerContext.isPrefetch());

    producer.produceResults(createConsumer(), settableProducerContext);

    }

   其他无关部分,我们先不关心了,直接看看,核心逻辑的操作

  1. 创建了一个消费者
  2. 传递给生产者来生产结果

打开我们的producer.producerResults,发现这只是个接口,这个其实就是面向接口的编程嘛,无论我们的请求需要做什么操作,这里只是通知生产者要开始生产工作了而已.

   前面我们已经提到了网络数据的producer是如何一步一步包装,然后创建的,我们还是以第一次网络请求的数据做参照,但是涉及到的producer也是比较多的,我们就挑选最先处理的producer和最后处理的producer和中间有代表性的一两个producer来做说明

   再来回顾一下,producer的相关过程,网络获取数据的producer会一步步包装,最后包装给BitmapMemoryCacheGetProducer,就是内存获取的producer,因而最终的producer就是BitmapMemoryCacheGetProducer,即这个调用的producer就是我们的BitmapMemoryCacheGetProducer

那么现在就可以从BitmapMemoryCacheGetProducer的produceResult来入手了

BitmapMemoryCacheGetProducer的继承体系

Producer

    --| BitmapMemoryCacheProducer

        --| BitmapMemoryCacheGetProducer

BitmapMemoryCacheGetProducer只是一个负责从内存中获取对应的数据的producer,查看其源码,发现没有复写produceResult方法,那就查看基类的produceResult

BitmapMemoryCacheProducer.produceResults() 源码

从类的名字,便可以知道,这个只是用于内存存取的producer,因而在producerResult的时候,会先从自己的内存中获取一下,查看是否存在于内存中,如果存在,直接获取到通知consumer即可,如果内存中不存在,才会去通知下一个处理器来处理这些事情,下个处理器在处理完成这些数据后,还是会通知消费者即回调的方式,来完成后续的操作,这就是生成处理完成的数据,处理完的结果如何应该保存到内存中呢?肯定是要生成一个key,然后将这个key保存到内存中.

 @Override
public void produceResults(
final Consumer<CloseableReference<CloseableImage>> consumer,
final ProducerContext producerContext) { final ProducerListener listener = producerContext.getListener();
final String requestId = producerContext.getId();
listener.onProducerStart(requestId, getProducerName());
final ImageRequest imageRequest = producerContext.getImageRequest();
final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest); CloseableReference<CloseableImage> cachedReference = mMemoryCache.get(cacheKey); if (cachedReference != null) {
boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality();
if (isFinal) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "true") : null);
consumer.onProgressUpdate(1f);
}
consumer.onNewResult(cachedReference, isFinal);
cachedReference.close();
if (isFinal) {
return;
}
} if (producerContext.getLowestPermittedRequestLevel().getValue() >=
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
consumer.onNewResult(null, true);
return;
} Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(consumer, cacheKey);
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
mNextProducer.produceResults(wrappedConsumer, producerContext);
}

消费者是如何处理这个回调呢

BitmapMemoryCacheProducer.wrapConsumer() 源码

 protected Consumer<CloseableReference<CloseableImage>> wrapConsumer(
final Consumer<CloseableReference<CloseableImage>> consumer,
final CacheKey cacheKey) {
return new DelegatingConsumer<
CloseableReference<CloseableImage>,
CloseableReference<CloseableImage>>(consumer) {
@Override
public void onNewResultImpl(CloseableReference<CloseableImage> newResult, boolean isLast) {
// ignore invalid intermediate results and forward the null result if last
if (newResult == null) {
if (isLast) {
getConsumer().onNewResult(null, true);
}
return;
}
// stateful results cannot be cached and are just forwarded
if (newResult.get().isStateful()) {
getConsumer().onNewResult(newResult, isLast);
return;
}
// if the intermediate result is not of a better quality than the cached result,
// forward the already cached result and don't cache the new result.
if (!isLast) {
CloseableReference<CloseableImage> currentCachedResult = mMemoryCache.get(cacheKey);
if (currentCachedResult != null) {
try {
QualityInfo newInfo = newResult.get().getQualityInfo();
QualityInfo cachedInfo = currentCachedResult.get().getQualityInfo();
if (cachedInfo.isOfFullQuality() || cachedInfo.getQuality() >= newInfo.getQuality()) {
getConsumer().onNewResult(currentCachedResult, false);
return;
}
} finally {
CloseableReference.closeSafely(currentCachedResult);
}
}
}
// cache and forward the new result
CloseableReference<CloseableImage> newCachedResult =
mMemoryCache.cache(cacheKey, newResult);
try {
if (isLast) {
getConsumer().onProgressUpdate(1f);
}
getConsumer().onNewResult(
(newCachedResult != null) ? newCachedResult : newResult, isLast);
} finally {
CloseableReference.closeSafely(newCachedResult);
}
}
};
}

在这里用到了代理设计模式,因为呢,每个producer都会调用consumer的方法,但是不同的producer需要在原有consumer的基础上处理自己的一些逻辑,这里呢?就需要将原来的consumer进行代理,调用时,先处理自己的逻辑,然后调用原有consumer的相关方法即可.

这里我们看到消费者是在产生新的结果时会缓存这个结果,但是这个只是基类BitmapMemoryCacheProducer的wrapConsumer的方法,我们这个实现类BitmapMemoryCacheGetProducer只是用于内存获取而已,所以,不会涉及到内存缓存这块,只是获取,所以BitmapMemoryCacheGetProducer的wrapConsumer只是返回方法中的consumer.

看完了这个内存缓存的producer后,我们再看看最后的producer,即网络数据获取的相关producer:NetworkFetchProducer

Fresco 源码分析(三) Fresco服务端处理(3) DataSource到Producer的适配器逻辑以及BitmapMemoryCacheProducer处理的逻辑的更多相关文章

  1. Fresco 源码分析(三) Fresco服务端处理(1) ImagePipeline为何物

    4.3 服务端的处理 备注: 因为是分析,而不是设计,所以很多知识我们类似于插叙的方式叙述,就是用到了哪个知识点,我们再提及相关的知识点,如果分析到了最后,我想想是不是应该将这个架构按照设计的方式,重 ...

  2. Fresco 源码分析(三) Fresco服务端处理(2) Producer具体实现的内容

    我们以mProducerFactory.newNetworkFetchProducer()为例,因为这些创建新的producer的方式类似,区别在于是否有包装的处理器,即如果当前处理器中没有正在处理的 ...

  3. Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通

    4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...

  4. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  5. Fresco 源码分析(二) Fresco客户端与服务端交互(2) Fresco.initializeDrawee()分析 续

    4.2.1.2 Fresco.initializeDrawee()的过程 续 继续上篇博客的分析Fresco.initializeDrawee() sDraweeControllerBuilderSu ...

  6. 【Netty源码分析】Netty服务端bind端口过程

    这一篇博客我们介绍一下Netty服务端绑定端口的过程,我们通过跟踪代码一直到NIO原生绑定端口的操作. 绑定端口操作 ChannelFuture future = serverBootstrap.bi ...

  7. Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析

    4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用 DraweeHierachy (I) --| SettableDraweeHierarchy (I) ------| Gen ...

  8. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  9. angular源码分析:$compile服务——directive他妈

    一.directive的注册 1.我们知道,我们可以通过类似下面的代码定义一个指令(directive). var myModule = angular.module(...); myModule.d ...

随机推荐

  1. MyEclipse------随机流(能读也能写数据)

    RandomAccessFile流指向文件时,不刷新文件. 其中seek(long a)用来定位RandomAccessFile流的读写位置,其中参数a确定读写位置距离文件开头的字节个数. other ...

  2. Matalab IFS分形算法

    IFS 算法代码 function IFS_draw(M,p) N=; :length(p); eval(['a',num2str(k),'=reshape(M(',num2str(k),',:),2 ...

  3. Centos 5.x/6.x 配置163网易yum源

    Centos系统默认都是系统自带的yum源,国内用户用yum源安装比较慢,为了提高效率,一般我们会配置国内的yum源.国内比较好的yum源有网易yum源.搜狐yum源等. 我感觉网易的yum源比较好用 ...

  4. IIS6.0文件解析漏洞小结

    今天搞站,本来这个站是aspx的,webserver是IIS6.0的,进入后台之后,发现有一个上传图片的地方,于是,我就上传了一张asp/aspx的一句话图片木马,但是用菜刀连接的时候,没有成功get ...

  5. object-c 的ARC 问答/介绍

    原文:http://blog.csdn.net/kmyhy/article/details/8895606 概念" Clangstatic analyzer "是一个非常有用的查找 ...

  6. linux rpm 安装包 信息查询

    来源:http://blog.csdn.net/namesliu/article/details/6004388 以CentOS5.5 中已经集成安装了 Apache.MySQL.PHP作为样例,我们 ...

  7. 百度文库,linux下安装oracle客户端

    linux单独安装oracle client(oracle客户端) 更新:2013-10-17 18:30 | 标签:linux oracle   1.要远程使用oracle,先下载下面三个文件,注意 ...

  8. 转 XenServer、XenCenter安装测试

    本文转自:http://blog.sina.com.cn/s/blog_5611597901014ze4.html 系统环境:win7 64bit  vmware-8.0.1 镜像文件:XenServ ...

  9. 【原创】angularjs1.3.0源码解析之scope

    Angular作用域 前言 之前我们探讨过Angular的执行流程,在一切准备工作就绪后(我是指所有directive和service都装载完毕),接下来其实就是编译dom(从指定的根节点开始遍历do ...

  10. 【分享】4款WiFi广告营销利器推荐

    随着WiFi的普及,相信大家已经发现很多公共场合连接WiFi的时候会要求登录,这个就是所谓的WiFi广告了. 什么是WiFi广告呢?(以下引用百科)       WiFi广告是目前WiFi营销的主要方 ...