Fresco源码分析-Fresco初始化

作者: susion哒哒 | 来源:发表于2018-04-03 19:03 被阅读103次

本文为分析Fresco源码第一篇,基于fresco 1.8.1

Fresco官网对于Fresco设计的基本概述

ImagePipeline

image pipeline 主要负责图片的加载和缓存工作。 可以从网路、本地内存、app res中加载图片。它具有三层缓存,其中两个在内存中,另一个在手机本地存储中。

Drawees

Drawees主要负责图片的展示工作。在图片完全加载之前他可以显示一个占位图,当图片不在屏幕上显示时,它可以自动释放图片所占用的内存。

从Fresco初始化看Fresco的基本组件

Fresco.java

public static void initialize(
    Context context,
    @Nullable ImagePipelineConfig imagePipelineConfig,
    @Nullable DraweeConfig draweeConfig) {
    //...
    if (imagePipelineConfig == null) {
        ImagePipelineFactory.initialize(context);
    } else {
        ImagePipelineFactory.initialize(imagePipelineConfig);
    }
    initializeDrawee(context, draweeConfig);
}

/** 初始化Drawee. */
private static void initializeDrawee(Context context,@Nullable DraweeConfig draweeConfig) {
    sDraweeControllerBuilderSupplier =
        new PipelineDraweeControllerBuilderSupplier(context, draweeConfig);
    SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}

从Fresco的初始化可以看出Fresco的基本组件为:ImagePipelineDrawee,接下来仔细看一下这两个都是负责哪些事情:

ImagePipeline

由于ImagePipeLine是一个功能十分多的组件,它由ImagePipelineFactory负责创建,由ImagePipelineConfig负责配置。ImagePipelineFactory提供一些ImagePipeline组成的组件,比如缓存。
ImagePipelineConfig主要负责配置ImagePipeline的网络相关选项和缓存相关选项等等。

ImagePipelineFactory.java

    public ImagePipeline getImagePipeline() {
        if (mImagePipeline == null) {
        mImagePipeline =
            new ImagePipeline(
                getProducerSequenceFactory(),
                mConfig.getRequestListeners(),
                mConfig.getIsPrefetchEnabledSupplier(),
                getBitmapMemoryCache(),
                getEncodedMemoryCache(),
                getMainBufferedDiskCache(),
                getSmallImageBufferedDiskCache(),
                mConfig.getCacheKeyFactory(),
                mThreadHandoffProducerQueue,
                Suppliers.of(false));
        }
        return mImagePipeline;
    }

ImagePipelineConfig.java

    public class ImagePipelineConfig {
        //...
        private final NetworkFetcher mNetworkFetcher;
        private final int mHttpNetworkTimeout;
        @Nullable private final PlatformBitmapFactory mPlatformBitmapFactory;
        private final PoolFactory mPoolFactory;
        private final ProgressiveJpegConfig mProgressiveJpegConfig;
        private final Set<RequestListener> mRequestListeners;
        private final boolean mResizeAndRotateEnabledForNetwork;
        private final DiskCacheConfig mSmallImageDiskCacheConfig;
        @Nullable private final ImageDecoderConfig mImageDecoderConfig;
        private final ImagePipelineExperiments mImagePipelineExperiments;
        //...
    }

Drawee

在上面的initializeDrawee()方法中可以看到,在初始化SimpleDraweeView之前,先初始化了PipelineDraweeControllerBuilderSupplier,那么这个类是干什么的?

PipelineDraweeControllerBuilderSupplier很简单,就是帮助PipelineDraweeControllerBuilder提供了ImagePipelinePipelineDraweeControllerFactory。顾名思义, PipelineDraweeControllerFactory是用来生产PipelineDraweeController的。看源码可以知道,ImagePipeline是为方便PipelineDraweeController获得缓存。

PipelineDraweeControllerBuilder.java

 @Override
  protected PipelineDraweeController obtainController() {
    DraweeController oldController = getOldController();
    PipelineDraweeController controller;
    if (oldController instanceof PipelineDraweeController) {
      controller = (PipelineDraweeController) oldController;
      controller.initialize(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext(),
          mCustomDrawableFactories,
          mImageOriginListener);
    } else {
      controller =
          mPipelineDraweeControllerFactory.newController(
              obtainDataSourceSupplier(),
              generateUniqueControllerId(),
              getCacheKey(),
              getCallerContext(),
              mCustomDrawableFactories,
              mImageOriginListener);
    }
    return controller;
  }

  //CacheKey 由 mImagePipeline.getCacheKeyFactory()。提供

其实上面层层构造,最后是为了产生一个十分关键的对象PipelineDraweeController

PipelineDraweeController

先来看一下官方注释:

Drawee controller that bridges the image pipeline with {@link SettableDraweeHierarchy}. <p> The
hierarchy's actual image is set to the image(s) obtained by the provided data source。

大致就是 PipelineDraweeControllerImagePipelineDrawee在图片处理流程中的结合点。即把ImagePipeline获取的图片数据传递给Drawee

从这个类的属性也可以看出它所承担的工作:

PipelineDraweeController.java

//Drawee相关
private final Resources mResources;
private final DrawableFactory mAnimatedDrawableFactory;
@Nullable
private final ImmutableList<DrawableFactory> mGlobalDrawableFactories;
//数据缓存相关
private @Nullable MemoryCache<CacheKey, CloseableImage> mMemoryCache;
private CacheKey mCacheKey;
// Constant state (non-final because controllers can be reused)
private Supplier<DataSource<CloseableReference<CloseableImage>>> mDataSourceSupplier;

不过上面官方注释指出的是图片数据传递给了SettableDraweeHierarchy,而并没有直接传递给Drawee。那先看一眼SettableDraweeHierarchy这个类大概是干什么吧。

SettableDraweeHierarchy.java

Interface that represents a settable Drawee hierarchy. Hierarchy should display a placeholder
image until the actual image is set. In case of a failure, hierarchy can choose to display
a failure image.

恩,明白,大致是控制加载不同阶段图片显示的切换的

继续来看Drawee的初始化:

初始化所做的工作十分简单:

SimpleDraweeView.java

 private void init(Context context, @Nullable AttributeSet attrs) {
    if (isInEditMode()) {
      return;
    }
    Preconditions.checkNotNull(
        sDraweeControllerBuilderSupplier,
        "SimpleDraweeView was not initialized!");
    mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get();

    if (attrs != null) {
      TypedArray gdhAttrs = context.obtainStyledAttributes(
          attrs,
          R.styleable.SimpleDraweeView);
      try {
        if (gdhAttrs.hasValue(R.styleable.SimpleDraweeView_actualImageUri)) {
          setImageURI(
              Uri.parse(gdhAttrs.getString(R.styleable.SimpleDraweeView_actualImageUri)),
              null);
        } else if (gdhAttrs.hasValue((R.styleable.SimpleDraweeView_actualImageResource))) {
          int resId = gdhAttrs.getResourceId(
              R.styleable.SimpleDraweeView_actualImageResource,
              NO_ID);
          if (resId != NO_ID) {
            setActualImageResource(resId);
          }
        }
      } finally {
        gdhAttrs.recycle();
      }
    }
  }

判断SimpleDraweeControllerBuilder是否存在,不存在则初始化失败。如果设置SimpleDraweeView的属性,则对属性做相应的处理。

额。上面我们看了PipelineDraweeController。那SimpleDraweeController又是什么呢?

SimpleDraweeController

其实SimpleDraweeController就是PipelineDraweeController。这点可以从类的继承层次可以看出:

PipelineDraweeControllerBuilderSupplier implements Supplier<PipelineDraweeControllerBuilder> 

PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<PipelineDraweeControllerBuilder

 AbstractDraweeControllerBuilder <
    BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
    REQUEST,
    IMAGE,
    INFO>
    implements SimpleDraweeControllerBuilder

上面对于Fresco的初始化大致已经分析完成了,对于Fresco图片加载的框架也基本比较清晰了,大概可以用下面这张图描述:

FrescoBasicArticture.png

可能存在一些问题,待后续完整阅读后,会慢慢更正。

相关文章

  • Fresco源码分析-Fresco初始化

    本文为分析Fresco源码第一篇,基于fresco 1.8.1。 Fresco官网对于Fresco设计的基本概述 ...

  • Fresco图片显示原理浅析

    (第一篇)Fresco架构设计赏析 (第二篇)Fresco缓存架构分析 本文是Fresco源码分析系列第三篇文章,...

  • Fresco架构设计赏析

    本文是Fresco源码分析系列的开篇,主要分析Fresco的整体架构、各个组成模块的功能以及图片加载流程,希望通过...

  • 2019Android面试Fresco架构详解

    本文是Fresco源码分析系列的开篇,主要分析Fresco的整体架构、各个组成模块的功能以及图片加载流程,希望通过...

  • Fresco缓存设计分析

    (第一篇)Fresco架构设计赏析 本文是Fresco源码分析系列第二篇文章,主要来看一下Fresco中有关图片缓...

  • Fresco源码分析之Controller

    如果你是第一次看我的Fresco的源码分析系列文章,这里强烈推荐你先阅读我的前面两篇文章Fresco源码分析之Dr...

  • Fresco的源码学习

    前言 Fresco android图片加载的框架,facebook出品。 本文是对Fresco框架源码的阅读学习后...

  • Fresco源码分析(一)

    Fresco学习中文地址:Fresco中文学习 Fresco Javadoc地址:Javadoc Fresco初始...

  • 浅谈Fresco编码图片缓存

    (第一篇)Fresco架构设计赏析 (第二篇)Fresco缓存架构分析 (第三篇)Fresco图片显示原理浅析 通...

  • Fresco源码分析-BitmapMemoryCacheProd

    前面几节大致了解了Fresco中的Producer,并分析了NetworkFetchProducer。接下来就大致...

网友评论

本文标题:Fresco源码分析-Fresco初始化

本文链接:https://www.haomeiwen.com/subject/qnmchftx.html