天天看點

Fresco源碼解析 - 初始化過程分析

Fresco源碼解析 - 初始化過程分析

使用Fresco之前,一定先要進行初始化,一般初始化的工作會在

Application.onCreate()

完成,當然也可以在使用

Drawee

之前完成。

Fresco本身提供了兩種初始化方式,一種是使用使用預設配置初始化,另一種是使用使用者自定義配置。

如下代碼是Fresco提供的兩個初始化方法。第一個隻需要提供一個

Context

參數,第二個還需要提供 ImagePipeline 的配置執行個體 -

ImagePipelineConfig

/** Initializes Fresco with the default config. */
public static void initialize(Context context) {
  ImagePipelineFactory.initialize(context);
  initializeDrawee(context);
}
           
/** Initializes Fresco with the specified config. */
public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig) {
  ImagePipelineFactory.initialize(imagePipelineConfig);
  initializeDrawee(context);
}
           

先來分析一下第一種方式。

開始初始化

Fresco.initialized(context)
           

使用預設參數進行初始化

com.facebook.drawee.backends.pipeline.Fresco

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

其中

ImagePipeline

負責擷取圖像資料,可以是網絡圖檔,也可以是本地圖檔。這裡用一個 Factory -

ImagePipelineFactory

來建立預設的

ImagePipleline

建立 ImagePipeline

com.facebook.imagepipeline.core.ImagePipelineFactory

/** Initializes {@link ImagePipelineFactory} with default config. */
public static void initialize(Context context) {
  initialize(ImagePipelineConfig.newBuilder(context).build());
}
           

ImagePipelineConfig

ImagePipeline

的初始化工作提供了必需的參數,它的建構過程采用了Builder模式。

ImagePipelineConfig

中包含了很多參數,因為我們調用

Fresco.initialize()

的時候值傳遞了一個

context

參數,是以 Fresco 還沒有擷取任何使用者自定義的資料,是以全部使用預設值,

Builder

類隻提供了建構的過程,而預設值則需要等到建立

ImagePipelineConfig

時建立。

通過

Builder

的部分源碼可以看出,初始化一個

ImagePipeline

需要很多參數,這些參數的具體意義會在後續的博文中介紹。

public static class Builder {
  private Supplier<MemoryCacheParams> mBitmapMemoryCacheParamsSupplier;
  private CacheKeyFactory mCacheKeyFactory;
  private final Context mContext;
  private Supplier<MemoryCacheParams> mEncodedMemoryCacheParamsSupplier;
  private ExecutorSupplier mExecutorSupplier;
  private ImageCacheStatsTracker mImageCacheStatsTracker;
  private ImageDecoder mImageDecoder;
  private Supplier<Boolean> mIsPrefetchEnabledSupplier;
  private DiskCacheConfig mMainDiskCacheConfig;
  private MemoryTrimmableRegistry mMemoryTrimmableRegistry;
  private NetworkFetcher mNetworkFetcher;
  private PoolFactory mPoolFactory;
  private ProgressiveJpegConfig mProgressiveJpegConfig;
  private Set<RequestListener> mRequestListeners;
  private boolean mResizeAndRotateEnabledForNetwork = true;
  private DiskCacheConfig mSmallImageDiskCacheConfig;
  private AnimatedImageFactory mAnimatedImageFactory;

  // other methods
}
           

從 Fresco 的

initialize

方法中我們得知,

ImagePipelineConfig

是這麼建立的:

ImagePipelineConfig.newBuilder(context).build())
           

Builder

并沒有提供參數的預設值,那預設值肯定是在

buid()

方法完成指派。

com.facebook.imagepipeline.core.ImagePipelineFactory$Builder

public ImagePipelineConfig build() {
  return new ImagePipelineConfig(this);
}
           

由以上代碼可以看出,

build()

會建立一個

ImagePipelineConfig

,然後把

this

作為參數傳給構造函數,而

ImagePipelineConfig

的構造函數就是根據

Builder

來初始化自己。

初始化的政策非常簡單:

  • 如果

    builder

    中的參數值為空,則使用預設值。
  • 如果

    builder

    中的參數值不為空,則使用

    Builder

    提供的值。

可以通過一個具體的參數來看一下,如果

builder.mBitmapMemoryCacheParamsSupplier

為空,則

new DefaultBitmapMemoryCacheParamsSupplier()

,如果不空,則使用

builder.mBitmapMemoryCacheParamsSupplier

mBitmapMemoryCacheParamsSupplier =
    builder.mBitmapMemoryCacheParamsSupplier == null ?
        new DefaultBitmapMemoryCacheParamsSupplier(
            (ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
        builder.mBitmapMemoryCacheParamsSupplier;
           

最後把這個 build 出來的

ImagePipelineConfig

執行個體傳給

ImagePipelineFactory

的靜态方法

initialize

,完成初始化。

/** Initializes {@link ImagePipelineFactory} with the specified config. */
public static void initialize(ImagePipelineConfig imagePipelineConfig) {
  sInstance = new ImagePipelineFactory(imagePipelineConfig);
}
           

ImagePipelineFactory

的執行個體

sInstance

會在初始化 Drawee 的時候用到。

初始化 Drawee

通過以上分析我們了解到,

Fresco

會首先初始化

ImagePipeline

,并把

ImagePipeline

的執行個體儲存在一個

ImagePipelineFactory

類型的靜态變量中 -

sInstance

;然後開始初始化

Drawee

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

首先,

new

一個

PipelineDraweeControllerBuilderSupplier

,它是

PipelineDraweeControllerBuilder

的一個

Supplier

Supplier

不是由 JDK 提供的,而是 Fresco 直接從 guava 中移過來的,代碼簡單,隻提供了一個

get

方法。

/**
 * A class that can supply objects of a single type.  Semantically, this could
 * be a factory, generator, builder, closure, or something else entirely. No
 * guarantees are implied by this interface.
 *
 * @author Harry Heymann
 * @since 2.0 (imported from Google Collections Library)
 */
public interface Supplier<T> {
  /**
   * Retrieves an instance of the appropriate type. The returned object may or
   * may not be a new instance, depending on the implementation.
   *
   * @return an instance of the appropriate type
   */
  T get();
}
           

顧名思義,

Supplier

是一個提供者,使用者包括但不限于

factory

,

generator

,

builder

,

closure

,接口方法

get()

用于傳回它所提供的執行個體,需要注意的是,這個執行個體可以是建立的,也可以不是。

在這裡,

PipelineDraweeControllerBuilderSupplier

的用法更像是一個

Factory

,它實作了

Supplier

接口。

public class PipelineDraweeControllerBuilderSupplier implements
    Supplier<PipelineDraweeControllerBuilder> {

  private final Context mContext;
  private final ImagePipeline mImagePipeline;
  private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;
  private final Set<ControllerListener> mBoundControllerListeners;

  public PipelineDraweeControllerBuilderSupplier(Context context) {
    this(context, ImagePipelineFactory.getInstance());
  }

  public PipelineDraweeControllerBuilderSupplier(
      Context context,
      ImagePipelineFactory imagePipelineFactory) {
    this(context, imagePipelineFactory, null);
  }

  public PipelineDraweeControllerBuilderSupplier(
      Context context,
      ImagePipelineFactory imagePipelineFactory,
      Set<ControllerListener> boundControllerListeners) {
    mContext = context;
    mImagePipeline = imagePipelineFactory.getImagePipeline();
    mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory(
        context.getResources(),
        DeferredReleaser.getInstance(),
        imagePipelineFactory.getAnimatedDrawableFactory(),
        UiThreadImmediateExecutorService.getInstance());
    mBoundControllerListeners = boundControllerListeners;
  }

  @Override
  public PipelineDraweeControllerBuilder get() {
    return new PipelineDraweeControllerBuilder(
        mContext,
        mPipelineDraweeControllerFactory,
        mImagePipeline,
        mBoundControllerListeners);
  }
}
           

構造函數

PipelineDraweeControllerBuilderSupplier(Context context)

,使用了在

Fresco

initalize

方法中通過

ImagePipelineFactoryBuilder

建立的

ImagePipelineFactory

的執行個體。

this(context, ImagePipelineFactory.getInstance());
           

get

方法告訴我們,

ImagePipeline

會存儲在

PipelineDraweeController

中,關于

Controller

可以參考 Fresco源碼解析 - Hierarachy-View-Controller。

同時

PipelineDraweeController

也會存儲一個

mPipelineDraweeControllerFactory

public class PipelineDraweeControllerFactory {

  private Resources mResources;
  private DeferredReleaser mDeferredReleaser;
  private AnimatedDrawableFactory mAnimatedDrawableFactory;
  private Executor mUiThreadExecutor;

  public PipelineDraweeControllerFactory(
      Resources resources,
      DeferredReleaser deferredReleaser,
      AnimatedDrawableFactory animatedDrawableFactory,
      Executor uiThreadExecutor) {
    mResources = resources;
    mDeferredReleaser = deferredReleaser;
    mAnimatedDrawableFactory = animatedDrawableFactory;
    mUiThreadExecutor = uiThreadExecutor;
  }

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

這個

mPipelineDraweeControllerFactory

會通過

newController

來建立一個

PipelineDraweeController

的執行個體。

到底,初始化的工作就完成了。

以上分析雖然簡單,但是清楚地梳理了 Fresco 的初始化過程,不過任然是遠遠不夠的,由以上代碼可以看出,初始化對應元件(Drawee、ImagePipeline)時用到了很多的設計模式,如果不太熟悉這些設計模式,可能了解起來會比較吃力。更加關鍵的是,初始化對應的元件用到了大量的參數,每個參數背後又會牽扯到很多知識點,後續博文中,我們再來一一分析。

繼續閱讀