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. C++中尖括号和引号的区别---转载

    如果你还看一些别的C++教程,那么你可能很早就发现了,有些书上的#include命令写作#include <文件名>,但有时候又会出现#include "文件名".你会 ...

  2. VirtualBox:Fatal:Could not read from Boot Medium! System Halted解决措施

    打开VirtualBox加载XP虚拟机操作系统时,出现含有下面文字的错误:   Could not read from Boot Medium! System Halted   或下面图中所示错误: ...

  3. 离线渲染中的不规则光源(Meshlight)

    之前一直在考虑这样一个问题,在实际生活中的光源都是有体积的,但是图形学中,很多时候我们用简单的点光源,面光源,或者方向光来模拟实际生活中这些光源,势必会产生一些误差,同时导致很多效果不好做.那么在离线 ...

  4. nuget pack

    nuget spec nuget setApiKey yourkeynuget pack PluginMvc.Framework.csproj -Prop Configuration=Releasen ...

  5. oracle的主键

    1.关于主键:在建表时指定primary key字句即可:create table test( id number(6) primary key, name varchar2(30));如果是对于已经 ...

  6. struts2 + ajax + json的结合使用,实例讲解

    struts2用response怎么将json值返回到页面javascript解析,这里介绍一个struts2与json整合后包的用法. 1.准备工作 ①ajax使用Jquery:jquery-1.4 ...

  7. javascript模板插件amaze.js

    摘要: 最近在开发项目时,异步接口需要前端渲染数据,js拼接太低级,必然要用模板插件.之前用过基于jQuery的和juicer等插件,考虑到以后公司项目上的统一,移动端和pc端上的统一,以及可维护性, ...

  8. 基于Redis的短链接设计思路

    [Markdown阅读][1] 今天上班的时候收到一个需要短链接的需求,之前的做法都是使用了新浪的短链接API(https://api.weibo.com/2/short_url/shorten.js ...

  9. Excel导入导出,生成和下载Excel报表、附件等操作--ASP.NET

    public class OutExcel { public static void OutExcel_bb(DataTable dt, string thepath, string temppath ...

  10. [HDU5015]233 Matrix

    [HDU5015]233 Matrix 试题描述 In our daily life we often use 233 to express our feelings. Actually, we ma ...