4.2 Fresco客户端与服务端的交互(一) 解决Q1问题##

从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里好奇,才开始分析如何交互的,这样避免了思维的跳跃性)

既然我们想从这里入手,那么还是以controller的请求入手,因为请求是从这里发出去的,那么肯定入口就存在于AbstractDraweeController.submitRequest()方法,上源码: 在刚刚查看源码时,我们并没有提及到getDataSource()方法是如何实现的,我们先再浏览一遍submitRequest方法

  1. protected void submitRequest() {
  2. mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT);
  3. getControllerListener().onSubmit(mId, mCallerContext);
  4. mSettableDraweeHierarchy.setProgress(0, true);
  5. mIsRequestSubmitted = true;
  6. mHasFetchFailed = false;
  7. // ------------疑问点----
  8. mDataSource = getDataSource();
  9. if (FLog.isLoggable(FLog.VERBOSE)) {
  10. FLog.v(
  11. TAG,
  12. "controller %x %s: submitRequest: dataSource: %x",
  13. System.identityHashCode(this),
  14. mId,
  15. System.identityHashCode(mDataSource));
  16. }
  17. final String id = mId;
  18. final boolean wasImmediate = mDataSource.hasResult();
  19. final DataSubscriber<T> dataSubscriber =
  20. new BaseDataSubscriber<T>() {
  21. @Override
  22. public void onNewResultImpl(DataSource<T> dataSource) {
  23. // isFinished must be obtained before image, otherwise we might set intermediate result
  24. // as final image.
  25. boolean isFinished = dataSource.isFinished();
  26. float progress = dataSource.getProgress();
  27. T image = dataSource.getResult();
  28. if (image != null) {
  29. onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
  30. } else if (isFinished) {
  31. onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
  32. }
  33. }
  34. @Override
  35. public void onFailureImpl(DataSource<T> dataSource) {
  36. onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
  37. }
  38. @Override
  39. public void onProgressUpdate(DataSource<T> dataSource) {
  40. boolean isFinished = dataSource.isFinished();
  41. float progress = dataSource.getProgress();
  42. onProgressUpdateInternal(id, dataSource, progress, isFinished);
  43. }
  44. };
  45. mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
  46. }

在看到getDataSource方法时,我们查看其方法,发现是抽象方法,查看类的继承关系图,得知,实现类有两个PipelineDraweeController和VolleyDraweeController,这个就遇到点困难了,到底采用的是哪个呢?到这里就卡壳了,那么如何处理呢?我们要回到我们起点了,就是在写demo的时候,我们一般在Application 的实现类中的onCreate方法中,调用Fresco.initialize()方法,不得不从这里开始看,因为所有的初始化信息,是在这里实现的(这可不是步步高打火机,那里不会点哪里,哈哈哈)

4.2.1 Fresco初始化的过程##

为了要了解getDataSource()方法使用的是哪个实现类,我们从Fresco.initialize()方法入手,分析Fresco初始化的过程

在书写demo的时候,从官方的说明中,已经得知,一般是在Application的onCreate()方法中调用Fresco.initialize()方法,那么这里做了什么样的操作呢?从方法名也可知,这是做了初始化,但是具体需要初始化那些信息呢?

*** Fresco.initialize() 源码 ***

  1. /** Initializes Fresco with the default config. */
  2. public static void initialize(Context context) {
  3. ImagePipelineFactory.initialize(context);
  4. initializeDrawee(context);
  5. }

从上边的源码可知,初始化了两部分信息

  1. ImagePipelineFactory做了初始化
  2. 初始化了Drawee组件信息

note: 个人查看他人代码,可将这个过程当做图来处理,可以做广度查看,也可以按照深度查看,个人建议,广度做了解,了解当前方法的大致流程(对于书写比较规范的框架,一般是见名知意的)然后做每个方法的深度遍历,便了解,边做笔记。

上述已经得知,先做ImagePipelineFactory的初始化,然后初始化Drawee组件,那么就先查看ImagePipelineFactory的初始化

4.2.1.1 ImagePipelineFactory的初始化

*** ImagePipelineFactory.initialize() 源码 ***

  1. /** Initializes {@link ImagePipelineFactory} with default config. */
  2. public static void initialize(Context context) {
  3. initialize(ImagePipelineConfig.newBuilder(context).build());
  4. }
  5. /** Initializes {@link ImagePipelineFactory} with the specified config. */
  6. public static void initialize(ImagePipelineConfig imagePipelineConfig) {
  7. sInstance = new ImagePipelineFactory(imagePipelineConfig);
  8. }
  9. public ImagePipelineFactory(ImagePipelineConfig config) {
  10. mConfig = Preconditions.checkNotNull(config);
  11. }

初始化过程,构造了一个ImagePipelineConfig,然后将创建的ImagePipelineConfig用于初始化ImagePipelineFactory,即新建了一个ImagePipelineFactory,新创建的ImagePipelineFactory保存了ImagePipelineConfig的实例

note:这里再次使用了构造者模式

下面需要关注的就变为了ImagePipelineConfig.newBuilder(context).build()的操作

*** ImagePipelineConfig.newBuilder(context).build()的源码 ***

  1. public static Builder newBuilder(Context context) {
  2. return new Builder(context);
  3. }
  4. public static class Builder {
  5. ......
  6. private Builder(Context context) {
  7. // Doesn't use a setter as always required.
  8. mContext = Preconditions.checkNotNull(context);
  9. }
  10. ......
  11. public ImagePipelineConfig build() {
  12. return new ImagePipelineConfig(this);
  13. }
  14. }

从查看ImagePipelineConfig的上述源码,得知,核心的初始化方法,在Builder.build()方法中,而在builder中创建了一个ImagePipelineConfig对象,而依附的对象为builder,这就到了ImagePipelineConfig的核心处

  1. private ImagePipelineConfig(Builder builder) {
  2. mBitmapMemoryCacheParamsSupplier =
  3. builder.mBitmapMemoryCacheParamsSupplier == null ?
  4. new DefaultBitmapMemoryCacheParamsSupplier(
  5. (ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
  6. builder.mBitmapMemoryCacheParamsSupplier;
  7. mCacheKeyFactory =
  8. builder.mCacheKeyFactory == null ?
  9. DefaultCacheKeyFactory.getInstance() :
  10. builder.mCacheKeyFactory;
  11. mContext = Preconditions.checkNotNull(builder.mContext);
  12. mEncodedMemoryCacheParamsSupplier =
  13. builder.mEncodedMemoryCacheParamsSupplier == null ?
  14. new DefaultEncodedMemoryCacheParamsSupplier() :
  15. builder.mEncodedMemoryCacheParamsSupplier;
  16. mExecutorSupplier =
  17. builder.mExecutorSupplier == null ?
  18. new DefaultExecutorSupplier() :
  19. builder.mExecutorSupplier;
  20. mImageCacheStatsTracker =
  21. builder.mImageCacheStatsTracker == null ?
  22. NoOpImageCacheStatsTracker.getInstance() :
  23. builder.mImageCacheStatsTracker;
  24. mIsPrefetchEnabledSupplier =
  25. builder.mIsPrefetchEnabledSupplier == null ?
  26. new Supplier<Boolean>() {
  27. @Override
  28. public Boolean get() {
  29. return true;
  30. }
  31. } :
  32. builder.mIsPrefetchEnabledSupplier;
  33. mMainDiskCacheConfig =
  34. builder.mMainDiskCacheConfig == null ?
  35. getDefaultMainDiskCacheConfig(builder.mContext) :
  36. builder.mMainDiskCacheConfig;
  37. mMemoryTrimmableRegistry =
  38. builder.mMemoryTrimmableRegistry == null ?
  39. NoOpMemoryTrimmableRegistry.getInstance() :
  40. builder.mMemoryTrimmableRegistry;
  41. mPoolFactory =
  42. builder.mPoolFactory == null ?
  43. new PoolFactory(PoolConfig.newBuilder().build()) :
  44. builder.mPoolFactory;
  45. mProgressiveJpegConfig =
  46. builder.mProgressiveJpegConfig == null ?
  47. new SimpleProgressiveJpegConfig() :
  48. builder.mProgressiveJpegConfig;
  49. mRequestListeners =
  50. builder.mRequestListeners == null ?
  51. new HashSet<RequestListener>() :
  52. builder.mRequestListeners;
  53. mResizeAndRotateEnabledForNetwork = builder.mResizeAndRotateEnabledForNetwork;
  54. mSmallImageDiskCacheConfig =
  55. builder.mSmallImageDiskCacheConfig == null ?
  56. mMainDiskCacheConfig :
  57. builder.mSmallImageDiskCacheConfig;
  58. mAnimatedDrawableUtil = new AnimatedDrawableUtil();
  59. AnimatedDrawableBackendProvider animatedDrawableBackendProvider =
  60. new AnimatedDrawableBackendProvider() {
  61. @Override
  62. public AnimatedDrawableBackend get(AnimatedImageResult imageResult, Rect bounds) {
  63. return new AnimatedDrawableBackendImpl(mAnimatedDrawableUtil, imageResult, bounds);
  64. }
  65. };
  66. GingerbreadBitmapFactory factoryGingerbread = new GingerbreadBitmapFactory();
  67. DalvikBitmapFactory factoryICS = new DalvikBitmapFactory(
  68. new EmptyJpegGenerator(mPoolFactory.getPooledByteBufferFactory()),
  69. mPoolFactory.getSharedByteArray());
  70. ArtBitmapFactory factoryLollipop =
  71. new ArtBitmapFactory(mPoolFactory.getBitmapPool());
  72. mPlatformBitmapFactory =
  73. new PlatformBitmapFactory(
  74. factoryGingerbread,
  75. factoryICS,
  76. factoryLollipop);
  77. mAnimatedImageFactory = builder.mAnimatedImageFactory == null ?
  78. new AnimatedImageFactory(animatedDrawableBackendProvider, mPlatformBitmapFactory) :
  79. builder.mAnimatedImageFactory;
  80. mImageDecoder =
  81. builder.mImageDecoder == null ?
  82. new ImageDecoder(mAnimatedImageFactory, mPlatformBitmapFactory) :
  83. builder.mImageDecoder;
  84. mNetworkFetcher =
  85. builder.mNetworkFetcher == null ?
  86. new HttpUrlConnectionNetworkFetcher() :
  87. builder.mNetworkFetcher;
  88. }

上述源码是ImagePipelineConfig的构造,发现此处初始化涉及的信息比较多,为了方便理解,我们先从名称上做一下理解,一会儿用到的时候,再反过来查看相关的详情信息

此类的名称特别形象,就是ImagePipleline的配置类,这其中配置了比较核心的几项

  1. mBitmapMemoryCacheParamsSupplier 内存缓存数据的策略
  2. mCacheKeyFactory 缓存键值对的获取
  3. mExecutorSupplier 获取本地读写线程池,网络数据线程池,解码线程池,以及后台线程池
  4. mImageDecoder 解码器
  5. 网络数据获取器

    ......

ImagePipeLineConfig是一个比较核心的类,通过这个,我们可以得知,Freco初始化时,配置了大量的策略,可配置项很多,也就让我们的使用更加灵活和易于拓展

4.2.1.2 Fresco.initializeDrawee()的过程

  1. private static void initializeDrawee(Context context) {
  2. sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
  3. SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
  4. }

从上述可知,构造了一个sDraweeControllerBuilderSupplier,然后将这个supplier用于初始化SimpleDraweeView

哎!找到了,发现使用的是PipelineDraweeControllerBuilderSupplier,是不是分析到这里我们就可以结束了?答案是我们只是找到了用于初始化SimpleDraweeView的supplier是PipelineDraweeControllerBuilderSupplier,但是这个做的是怎么样的一个操作呢?我们下节再讨论

下篇链接: Fresco 源码分析(二) Fresco.initializeDrawee()分析 续 http://www.cnblogs.com/pandapan/p/4659960.html

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

Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题的更多相关文章

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

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

  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. android HDMI 清晰度 分辨率

    但改变分辨率时,发送广播即可: Intent intent_outputmode_change = new Intent(ACTION_OUTPUTMODE_CHANGE);     intent_o ...

  2. 怎样分析java线程堆栈日志

    注: 该文章的原文是由 Tae Jin Gu 编写,原文地址为 How to Analyze Java Thread Dumps 当有障碍,或者是一个基于 JAVA 的 WEB 应用运行的比预期慢的时 ...

  3. PHP中应用GD2函数在图像上添加文字

    <?php header("Content-type:text/html;charset=utf-8"); header("Content-type:image/g ...

  4. 命令行编译vs2013项目

    echo off path %SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319\ msbuild.exe .\src\ElectricManagement. ...

  5. 敲点JavaScript代码

    1. DOM DEMO-表格的行排序 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  6. [BZOJ2820]YY的GCD

    [BZOJ2820]YY的GCD 试题描述 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少 ...

  7. Sort List

    采用归并排序,通过定义快.慢两个指针来找到中点,再采用之前的排序算法进行归并. ListNode *listSort(ListNode *head) { //定义快慢指针,找到链表中心 ListNod ...

  8. openCV的基本操作

    http://www.cnblogs.com/luluathena/archive/2010/09/29/1838471.html

  9. zookeeper 用法和日常运维

    本文以ZooKeeper3.4.3版本的官方指南为基础:http://zookeeper.apache.org/doc/r3.4.3/zookeeperAdmin.html,补充一些作者运维实践中的要 ...

  10. python的类变量与实例变量

    python的类内部定义的变量 ,形式上没有区分实例变量和类变量(java的静态变量),测试结果如下: