Fresco圖片框架實(shí)現(xiàn)原理(二):DraweeController

接上文《Fresco圖片框架實(shí)現(xiàn)原理(一)》文末

private static void initializeDrawee(
      Context context,
      @Nullable DraweeConfig draweeConfig) {
    sDraweeControllerBuilderSupplier =
        new PipelineDraweeControllerBuilderSupplier(context, draweeConfig);
    SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);  }

在研究正真的PipelineDraweeController之前,先來(lái)看看PipelineDraweeControllerBuilder在Fresco中的構(gòu)造原理和過(guò)程

從上面的函數(shù)我們一個(gè)一個(gè)往里面點(diǎn)

image.png

PipelineDraweeControllerBuilderSupplier是一個(gè)提供者模式,主要是為了構(gòu)造PipelineDraweeControllerBuilder類(lèi)
圖像管道Drawee contrller builder的具體實(shí)現(xiàn)類(lèi)
PipelineDraweeControllerBuilder.png

AbstractDraweeControllerBuilder.png

SimpleDraweeControllerBuilder接口.png

這下繼承關(guān)系清除了:


繼承關(guān)系圖.png

SimpleDraweeControllerBuilder

/**
 * Interface for simple Drawee controller builders.
 */
   simple Drawee controller builders的接口
public interface SimpleDraweeControllerBuilder {

  /** Sets the caller context. */
  設(shè)置調(diào)用者上下文
  SimpleDraweeControllerBuilder setCallerContext(Object callerContext);

  /** Sets the uri. */
  設(shè)置圖像Uri
  SimpleDraweeControllerBuilder setUri(Uri uri);

  /** Sets the uri from a string. */
   設(shè)置圖像Uri
  SimpleDraweeControllerBuilder setUri(@Nullable String uriString);

  /** Sets the old controller to be reused if possible. */
   
 如果有可能,設(shè)置舊的controller 用以重用
  SimpleDraweeControllerBuilder setOldController(@Nullable DraweeController oldController);

  /** Builds the specified controller. */
  構(gòu)建具體的DraweeController  
  DraweeController build();
}

AbstractDraweeControllerBuilder 源碼

/**
 * Base implementation for Drawee controller builders.
 */
public abstract class AbstractDraweeControllerBuilder <
    BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
    REQUEST,
    IMAGE,
    INFO>
    implements SimpleDraweeControllerBuilder {

  private static final ControllerListener<Object> sAutoPlayAnimationsListener =
      new BaseControllerListener<Object>() {
        @Override
        public void onFinalImageSet(String id, @Nullable Object info, @Nullable Animatable anim) {
          if (anim != null) {
            anim.start();
          }
        }
      };

  private static final NullPointerException NO_REQUEST_EXCEPTION =
      new NullPointerException("No image request was specified!");

  // components
  private final Context mContext;
  private final Set<ControllerListener> mBoundControllerListeners;

  // builder parameters
  private @Nullable Object mCallerContext;
  圖片請(qǐng)求 ImageRequest
  private @Nullable REQUEST mImageRequest;
  底分辨率圖片請(qǐng)求
  private @Nullable REQUEST mLowResImageRequest;
  多圖片請(qǐng)求
  private @Nullable REQUEST[] mMultiImageRequests;
  private boolean mTryCacheOnlyFirst;
  數(shù)據(jù)源提供者
  private @Nullable Supplier<DataSource<IMAGE>> mDataSourceSupplier;
  private @Nullable ControllerListener<? super INFO> mControllerListener;
  private @Nullable ControllerViewportVisibilityListener mControllerViewportVisibilityListener;
  是否可點(diǎn)擊重試
  private boolean mTapToRetryEnabled;
 是否需要自動(dòng)播放動(dòng)畫(huà)
  private boolean mAutoPlayAnimations;
  private boolean mRetainImageOnFailure;
  private String mContentDescription;
  // old controller to reuse
  這個(gè)變量重要 重用的DraweeController ,其具體的對(duì)象,就給子類(lèi)去構(gòu)建
  private @Nullable DraweeController mOldController;

  private static final AtomicLong sIdCounter = new AtomicLong();

  protected AbstractDraweeControllerBuilder(
      Context context,
      Set<ControllerListener> boundControllerListeners) {
    mContext = context;
    mBoundControllerListeners = boundControllerListeners;
    init();
  }

  /** Initializes this builder. */
  private void init() {
    mCallerContext = null;
    mImageRequest = null;
    mLowResImageRequest = null;
    mMultiImageRequests = null;
    mTryCacheOnlyFirst = true;
    mControllerListener = null;
    mControllerViewportVisibilityListener = null;
    默認(rèn)false
    mTapToRetryEnabled = false;
    默認(rèn)不自動(dòng)播放
    mAutoPlayAnimations = false;
    mOldController = null;
    mContentDescription = null;
  }
   ....其他方法
   /** Builds a regular controller. */
   構(gòu)建一個(gè)常規(guī)的controller
  protected AbstractDraweeController buildController() {
    AbstractDraweeController controller = obtainController();
    controller.setRetainImageOnFailure(getRetainImageOnFailure());
    controller.setContentDescription(getContentDescription());
    controller.setControllerViewportVisibilityListener(getControllerViewportVisibilityListener());
    maybeBuildAndSetRetryManager(controller);
    maybeAttachListeners(controller);
    return controller;
  }
   /** Concrete builder classes should override this method to return a new controller. */
   這個(gè)抽象類(lèi)的唯一抽象方法,又子類(lèi)去實(shí)現(xiàn)構(gòu)造具體的類(lèi)
  protected abstract AbstractDraweeController obtainController();
   ...其他方法

AbstractDraweeControllerBuilder 的作用其實(shí)就是提供DraweeControllerBuilder所需要的所有成員變量,然后具體的變量值交給子類(lèi)PipelineDraweeControllerBuilder去獲取實(shí)現(xiàn),并設(shè)置這些成員變量
PipelineDraweeControllerBuilder源碼:


/**
 * Concrete implementation of ImagePipeline Drawee controller builder.
 * <p/> See {@link AbstractDraweeControllerBuilder} for more details.
 */
ImagePipeline Drawee controller builder.的具體實(shí)現(xiàn)

public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
    PipelineDraweeControllerBuilder,
    ImageRequest,
    CloseableReference<CloseableImage>,
    ImageInfo> {
   
  重要的成員變量圖像管道,final類(lèi)型,初始化一遍不在變化,上篇文章中提到可以從ImagePipelineFactory中獲取
  private final ImagePipeline mImagePipeline;

  重要的成員變量 PipelineDraweeControllerFactory是PipelineDraweeController工廠(chǎng)
  private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;

  @Nullable
  private ImmutableList<DrawableFactory> mCustomDrawableFactories;

  public PipelineDraweeControllerBuilder(
      Context context,
      PipelineDraweeControllerFactory pipelineDraweeControllerFactory,
      ImagePipeline imagePipeline,
      Set<ControllerListener> boundControllerListeners) {
    super(context, boundControllerListeners);
    mImagePipeline = imagePipeline;
    mPipelineDraweeControllerFactory = pipelineDraweeControllerFactory;
  }

  @Override
  public PipelineDraweeControllerBuilder setUri(@Nullable Uri uri) {
    if (uri == null) {
      return super.setImageRequest(null);
    }
    設(shè)置圖片Uri的的本質(zhì)是: 用此Uri構(gòu)建圖像請(qǐng)求ImageRequest,實(shí)際上Fresco加載圖片,都是構(gòu)造ImageRequest
    ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
        .setRotationOptions(RotationOptions.autoRotateAtRenderTime())
        .build();
    return super.setImageRequest(imageRequest);
  }

  @Override
  public PipelineDraweeControllerBuilder setUri(@Nullable String uriString) {
    if (uriString == null || uriString.isEmpty()) {
      return super.setImageRequest(ImageRequest.fromUri(uriString));
    }
    return setUri(Uri.parse(uriString));
  }
  ...其他方法

  父級(jí)抽象類(lèi)的抽象方法,重要方法  obtainController。
  @Override
  protected PipelineDraweeController obtainController() {
    先獲取之前設(shè)置的OldController
    DraweeController oldController = getOldController();
    PipelineDraweeController controller;
    
    if (oldController instanceof PipelineDraweeController) {
     如果oldController 是PipelineDraweeController的實(shí)例 ,就在從controller的實(shí)例上修改一些需要的值,不用再實(shí)例化一個(gè)controller
      controller = (PipelineDraweeController) oldController;
      controller.initialize(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext(),
          mCustomDrawableFactories);
    } else {
      如果oldcontroller ==null 使用PipelineDraweeControllerFactory重新生成一個(gè)新的controller
      controller = mPipelineDraweeControllerFactory.newController(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext(),
          mCustomDrawableFactories);
    }
    return controller;
  }
 ...其他方法
}

這個(gè)類(lèi)主要是為了設(shè)置一些builder所需要的值,并且構(gòu)造除樂(lè)具體的controller。PipelineDraweeController的實(shí)例
PipelineDraweeController這個(gè)類(lèi)是真正的DraweeController,這個(gè)下一章在分析。
PipelineDraweeControllerFactory是PipelineDraweeController的工廠(chǎng)類(lèi)。用于常見(jiàn)controller實(shí)例。


/**
 * Default implementation of {@link PipelineDraweeControllerFactory}.
 */
public class PipelineDraweeControllerFactory {

  private Resources mResources;
  private DeferredReleaser mDeferredReleaser;
  private DrawableFactory mAnimatedDrawableFactory;
  private Executor mUiThreadExecutor;
  private MemoryCache<CacheKey, CloseableImage> mMemoryCache;
  @Nullable
  private ImmutableList<DrawableFactory> mDrawableFactories;
  @Nullable
  private Supplier<Boolean> mDebugOverlayEnabledSupplier;

  public void init(
      Resources resources,
      DeferredReleaser deferredReleaser,
      DrawableFactory animatedDrawableFactory,
      Executor uiThreadExecutor,
      MemoryCache<CacheKey, CloseableImage> memoryCache,
      @Nullable ImmutableList<DrawableFactory> drawableFactories,
      @Nullable Supplier<Boolean> debugOverlayEnabledSupplier) {
    mResources = resources;
    mDeferredReleaser = deferredReleaser;
    mAnimatedDrawableFactory = animatedDrawableFactory;
    mUiThreadExecutor = uiThreadExecutor;
    mMemoryCache = memoryCache;
    mDrawableFactories = drawableFactories;
    mDebugOverlayEnabledSupplier = debugOverlayEnabledSupplier;
  }

  public PipelineDraweeController newController(
      Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext) {
    return newController(dataSourceSupplier, id, cacheKey, callerContext, null);
  }

  public PipelineDraweeController newController(
      Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext,
      @Nullable ImmutableList<DrawableFactory> customDrawableFactories) {
    Preconditions.checkState(mResources != null, "init() not called");
    // Field values passed as arguments so that any subclass of PipelineDraweeControllerFactory
    // can simply override internalCreateController() and return a custom Drawee controller
    PipelineDraweeController controller = internalCreateController(
        mResources,
        mDeferredReleaser,
        mAnimatedDrawableFactory,
        mUiThreadExecutor,
        mMemoryCache,
        mDrawableFactories,
        customDrawableFactories,
        dataSourceSupplier,
        id,
        cacheKey,
        callerContext);
    if (mDebugOverlayEnabledSupplier != null) {
      controller.setDrawDebugOverlay(mDebugOverlayEnabledSupplier.get());
    }
    return controller;
  }
  內(nèi)部創(chuàng)建PipelineDraweeController ,創(chuàng)建一個(gè)controller需要這么多參數(shù),所以需要上面講的重用controller的實(shí)例,只改變其中的幾個(gè)成員變量值就行了。
  protected PipelineDraweeController internalCreateController(
      Resources resources,
      DeferredReleaser deferredReleaser,
      DrawableFactory animatedDrawableFactory,
      Executor uiThreadExecutor,
      MemoryCache<CacheKey, CloseableImage> memoryCache,
      @Nullable ImmutableList<DrawableFactory> globalDrawableFactories,
      @Nullable ImmutableList<DrawableFactory> customDrawableFactories,
      Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext) {
    PipelineDraweeController controller = new PipelineDraweeController(
        resources,
        deferredReleaser,
        animatedDrawableFactory,
        uiThreadExecutor,
        memoryCache,
        dataSourceSupplier,
        id,
        cacheKey,
        callerContext,
        globalDrawableFactories);
    controller.setCustomDrawableFactories(customDrawableFactories);
    return controller;
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評(píng)論 25 709
  • 作者:董存亮 2010.10.29 正文: 自傳說(shuō)“盤(pán)古開(kāi)天地”和“女?huà)z造人”以降,智慧的人們就不斷思考:我們賴(lài)以...
    董存亮閱讀 762評(píng)論 0 0
  • 今日勵(lì)語(yǔ): 當(dāng)個(gè)人的才華還撐不起自己的野心時(shí),就應(yīng)該靜下心來(lái)學(xué)習(xí);當(dāng)個(gè)人的能力還駕馭不了你自己的目標(biāo)時(shí),就應(yīng)該沉下...
    七彩熏衣草閱讀 421評(píng)論 0 0
  • 零度打卡Day27 主題閱讀:《改變你一生的學(xué)習(xí)計(jì)劃》 第四章節(jié):高效學(xué)習(xí)方法筆記 每日橙思:偶也相信,雖然思維還...
    零度2013閱讀 248評(píng)論 0 0

友情鏈接更多精彩內(nèi)容