4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续

上节中我们提到两个核心的步骤

  1. obtainDataSourceSupplier()获取到了一个DataSourceSupplier
  2. 然后mPipelineDraweeControllerFactory类new了一个controller

还是先从广度分析,然后再深度分析

*** PipelineDraweeController.newController()源码 ***

在这里无非新创建了一个PipelineDraweeController

  public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
Object callerContext) {
return new PipelineDraweeController(
mResources,
mDeferredReleaser,
mAnimatedDrawableFactory,
mUiThreadExecutor,
dataSourceSupplier,
id,
callerContext);
}

那广度就先看到这里,这时就要再从深度开始看

这时我们要看以下的几个方法

  1. PipelineDraweeControllerBuilder.obtainDataSourceSupplier()的过程
  2. 新建PipelineDraweeController的过程

*** AbstractDraweeControllerBuilder.obtainDataSourceSupplier() ***

 /** Gets the top-level data source supplier to be used by a controller. */
protected Supplier<DataSource<IMAGE>> obtainDataSourceSupplier() {
if (mDataSourceSupplier != null) {
return mDataSourceSupplier;
} Supplier<DataSource<IMAGE>> supplier = null; // final image supplier;
if (mImageRequest != null) {
supplier = getDataSourceSupplierForRequest(mImageRequest);
} else if (mMultiImageRequests != null) {
supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests);
} // increasing-quality supplier; highest-quality supplier goes first
if (supplier != null && mLowResImageRequest != null) {
List<Supplier<DataSource<IMAGE>>> suppliers = new ArrayList<>(2);
suppliers.add(supplier);
suppliers.add(getDataSourceSupplierForRequest(mLowResImageRequest));
supplier = IncreasingQualityDataSourceSupplier.create(suppliers);
} // no image requests; use null data source supplier
if (supplier == null) {
supplier = DataSources.getFailedDataSourceSupplier(NO_REQUEST_EXCEPTION);
} return supplier;
}

老的分析思路继续,我们以第一次请求为例

先判断图片请求的信息,如果只是简单的mImageRequest,那么获取到getDataSourceSupplierForRequest()即可,然后,如果发现有渐进式的请求,那么supplier便基于目前的supplier创建新的supplier

*** AbstractDraweeControllerBuilder类的相关方法 ***

从下面的方法,便可知,创建了一个对应的Supplier而已,用于获取请求数据的supplier,注意在获取到的匿名的supplier的get方法中,我们看到调用的是getDataSourceForRequest方法,这个我们先备注一下: mark为Q3,便于我们插叙后,继续分析的入口点

  /** Creates a data source supplier for the given image request. */
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(REQUEST imageRequest) {
return getDataSourceSupplierForRequest(imageRequest, /* bitmapCacheOnly */ false);
} /** Creates a data source supplier for the given image request. */
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final boolean bitmapCacheOnly) {
final Object callerContext = getCallerContext();
return new Supplier<DataSource<IMAGE>>() {
@Override
public DataSource<IMAGE> get() {
return getDataSourceForRequest(imageRequest, callerContext, bitmapCacheOnly);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}

第1部分的深度我们就分析到这里

第2部分的深度分析:

4.2.1.2.5 插叙 --> AbstractDraweeController.submitRequest()分析 续

在我们分析的第二篇博客中,提到了AbstractDraweeController.submitRequest()方法,但是到了最后,我们只是留下了一个Q1问题,然后并没有继续分析下去,现在我们要插叙一段

  protected void submitRequest() {
......
mDataSource = getDataSource();
......
final String id = mId;
final boolean wasImmediate = mDataSource.hasResult();
final DataSubscriber<T> dataSubscriber......
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
}

这次,我们关注的核心是getDataSource()方法,然而这里是抽象类,具体使用的是哪个,当时我们无法分析,现在便可以知道,使用的是PipelineDraweeController类的方法

*** PipelineDraweeController.getDataSource 源码分析 ***

从以下的代码中,可以看出,只是从Supplier中获取到了dataSource而已

@Override

protected DataSource<CloseableReference> getDataSource() {

if (FLog.isLoggable(FLog.VERBOSE)) {

FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this));

}

return mDataSourceSupplier.get();

}

那么,这里就要考虑Supplier是从哪里初始化的,然后做了怎样的操作,查看当前的mDataSourceSupplier赋值的地方,得知,初始化的地方有两种方式,一种是构造,一种是直接的initialize,initialize的方法注释中已经告诉我们,这个是controller在detach的时候调用的,所以我们只需要查看构造即可

*** PipelineDraweeController的构造方法 ***

构造方法中调用了Init方法,在这里初始化了mDataSourceSupplier

public PipelineDraweeController(

Resources resources,

DeferredReleaser deferredReleaser,

AnimatedDrawableFactory animatedDrawableFactory,

Executor uiThreadExecutor,

Supplier<DataSource<CloseableReference>> dataSourceSupplier,

String id,

Object callerContext) {

super(deferredReleaser, uiThreadExecutor, id, callerContext);

mResources = resources;

mAnimatedDrawableFactory = animatedDrawableFactory;

init(dataSourceSupplier);

}

private void init(Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier) {
mDataSourceSupplier = dataSourceSupplier;
}

那么现在需要考虑的就是构造方法在哪里进行的调用,Alt+F7快捷键查看调用的地方,发现只有一处地方,就是我们的PipelineDraweeControllerFactory.newController()的方法,而这个方法我们之前已经分析过了

,现在稍微总结一下:

就是说每次在生成请求的时候,即AbstractDraweeController在submitRequest的时候,都会去向Supplier中获取到数据源DataSource,这个数据源是在AbstractDraweeControllerBuilder.getDataSourceSupplierForRequest()中的get方法中获取到的数据源,所以已经将服务端的supplier的生成和客户端的supplier的使用已经结合了起来.

但是还是没看到请求是怎么发送出去的,然后请求回来的数据是如何更新UI的.

在Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析(http://www.cnblogs.com/pandapan/p/4644195.html) 中我们已经分析了请求回来的数据是如何更新的,这个是通过给DataSource订阅观察者,然后去更新UI数据,这个具体的细节,我们之后再分析,这个已经超出了我们要分析的如何发送请求的范围

现在我们要分析我们的Q3问题,即请求是如何发送出去的

4.2.1.2.6 AbstractDraweeControllerBuilder是如何发送请求的 即分析Q3问题

在上面已经提到了,客户端在DraweeController中发送请求的过程中,会调用Supplier的get方法,那么在这里边调用到了AbstractDraweeControllerBuilder.getDataSourceSupplierForRequest()方法中生成的匿名supplier的get()方法

*** AbstractDraweeControllerBuilder.getDataSourceSupplierForRequest()方法 ***

在以下的方法中,我们看到,匿名的Supplier的get方法中,调用的是AbstractDraweeControllerBuilder自身的getDataSourceForRequest()方法返回的Supplier

  /** Creates a data source supplier for the given image request. */
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final boolean bitmapCacheOnly) {
final Object callerContext = getCallerContext();
return new Supplier<DataSource<IMAGE>>() {
@Override
public DataSource<IMAGE> get() {
return getDataSourceForRequest(imageRequest, callerContext, bitmapCacheOnly);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}

那么就继续跟踪呗,发现其为抽象方法,那么跟踪到子类,这时候,我们已经知道使用的是PipelineDraweeControllerBuilder,

*** PipelineDraweeControllerBuilder.getDataSourceForRequest()方法 ***

  @Override
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
boolean bitmapCacheOnly) {
if (bitmapCacheOnly) {
return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext);
} else {
return mImagePipeline.fetchDecodedImage(imageRequest, callerContext);
}
}

我们模拟的请求是显示到UI层,所以走的是else,即mImagePipeline.fetchDecodeImage();

那么这时候就到了ImagePipeline了,这部分用到了包装的设计模式,以及生产消费的设计模式,又属于另外一部分了,其实到这里,我们才算接触到ImagePipeline请求的核心,这也是Fresco设计的巧妙之处,很多知识不需要我们关心,我们一般来讲,只需要用到SimpleDraweeView即可

到这里,Fresco客户端与服务端的交互分析完毕,下一章节便是,服务端的请求是如何发送出去的以及请求回来的数据如何通过回调通知客户端的

下篇博客链接 : Fresco 源码分析(三) Fresco服务端处理(1) ImagePipeline为何物 (http://www.cnblogs.com/pandapan/p/4719918.html)

安卓源码分析群: Android源码分析QQ1群号:164812238

Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通的更多相关文章

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

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

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

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

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

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

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

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

  5. motan源码分析四:客户端调用服务

    在第一章中,我们分析了服务的发布与注册,本章中将简单的分析一下客户端调用服务的代码及流程,本文将以spring加载的方式进行分析. 1.在DemoRpcClient类的main()方法中加载类: Ap ...

  6. Fresco 源码分析(三) Fresco服务端处理(3) DataSource到Producer的适配器逻辑以及BitmapMemoryCacheProducer处理的逻辑

    4.3.1.2.1 Producer和DataSource之间适配器处理的逻辑 还是从程序的入口开始说吧 CloseableProducerToDataSourceAdapter.create() 源 ...

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

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

  8. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  9. Tomcat源码分析二:先看看Tomcat的整体架构

    Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...

随机推荐

  1. Nagios页面介绍(四)

    四.nagios页面介绍 Nagios 4.0.8版本登录后图片

  2. golang社工库数据扫描程序

    https://github.com/xiaojiong/scanfile 演示站点: http://www.weigongkai.com/   7G数据 2s完成扫描 package scanfil ...

  3. MYSQL远程登录权限设置(转)

    Mysql默认关闭远程登录权限,如下操作允许用户在任意地点登录: 1. 进入mysql,GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY ...

  4. C#设计模式(3):抽象工厂模式(Abstract Factory)(转载)

    概述 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来 ...

  5. html-php深入理解

    不再纠结div p span. 写html的时候, 在头脑中, 要等同于/实际上就相当于写一篇图文混排的word文档, 有主标题/子标题, 有正文段落等等. 要根据这些标签的本身的语义来使用! div ...

  6. JavaScript 中 for in 循环和数组的问题

    本文由 伯乐在线 - ElvisKang 翻译,进林 校稿.未经许可,禁止转载!英文出处:adripofjavascript.com.欢迎加入翻译小组. JavaScript的for…in循环用于迭代 ...

  7. 微信红包中使用的技术:AA收款+随机算法

    除夕夜你领到红包了吗?有的说“我领了好几K!”“我领了几W!” 土豪何其多,苦逼也不少!有的说“我出来工作了,没压岁钱了,还要发红包”.那您有去抢微信红包吗?微信群中抢“新年红包”春节爆红.618微信 ...

  8. ajax 之js读取xml的多浏览器兼容

    主要是分为两大类:IE.其它浏览器 IE8以下只支持这种 InputVoltage.innerText = xmlDoc.getElementsByTagName(id)[0].text, 其它浏览器 ...

  9. 在生产环境使用Docker部署应用

    导读 Docker现在越来越流行,但是真正在生产环境部署Docker还是个比较新的概念,还没有一个标准的流程.作者是ROR的程序员,作者结合平时的部署经验,联系Docker的特点,向大家分享了其在生产 ...

  10. Autolayout及VFL经验分享

    http://www.cocoachina.com/industry/20131108/7322.html 这篇不是什么教程.Cocoa autolayout出来蛮久了.以前多次想去深入研究一下,每次 ...