Fresco源碼分析(一)

Fresco學習中文地址:Fresco中文學習

Fresco Javadoc地址:Javadoc

Fresco初始化分析:

在Application中加入:

Fresco.initialize(this);

請看我的注釋:

/*
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.drawee.backends.pipeline;

import *

/**
 * Fresco entry point.(總體入口點)
 *
 * <p/> You must initialize this class before use. The simplest way is to just do
 * {#code Fresco.initialize(Context)}.
 * (指明了一個簡單例子)
 */
public class Fresco {
  private static PipelineDraweeControllerBuilderSupplier sDraweeControllerBuilderSupplier; //業(yè)務邏輯工廠

  private Fresco() {}

  /** 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);
  }

  private static void initializeDrawee(Context context) {
    sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
    SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier); // 這個SimpleDraweeView是在布局中使用的代理Imageview,掛在一堆轉換邏輯
  }

  /** Gets the supplier of Fresco Drawee controller builders. */
  public static PipelineDraweeControllerBuilderSupplier getDraweeControllerBuilderSupplier() {
    return sDraweeControllerBuilderSupplier; // 這貨給外部使用,看需求而定
  }

  /** Returns a new instance of Fresco Drawee controller builder. */
  public static PipelineDraweeControllerBuilder newDraweeControllerBuilder() {
    return sDraweeControllerBuilderSupplier.get(); // 給外部需求所用,拿到一個新的業(yè)務邏輯工廠對象
  }

  public static ImagePipelineFactory getImagePipelineFactory() {
    return ImagePipelineFactory.getInstance(); // 外部使用的管道類,這貨檢查是否初始化
  }

  /** Gets the image pipeline instance. */
  public static ImagePipeline getImagePipeline() {
    return getImagePipelineFactory().getImagePipeline();// 外部使用的管道類,這貨檢查是否初始化,沒有給你個新的,工廠模式
  }

  /** Shuts Fresco down. */
  public static void shutDown() { //Application 退出調用,避免內存泄露
    sDraweeControllerBuilderSupplier = null;
    SimpleDraweeView.shutDown();
    ImagePipelineFactory.shutDown();
  }
}

初始化翻譯就這樣:

Fresco.initialize() ===> Fresco.initializeDrawee() ===> SimpleDraweeView.initialize();

請繼續(xù)看我的注釋:

/*
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.drawee.view;

import *

/**
 * This view takes a uri as input and internally builds and sets a controller.(這個類就是掛載url和control準備)
 *
 * <p>This class must be statically initialized in order to be used. If you are using the Fresco
 * image pipeline, use {@link com.facebook.drawee.backends.pipeline.Fresco#initialize} to do this.
 * (官方教育你,先初始化Fresco.initialize)
 */
public class SimpleDraweeView extends GenericDraweeView { // 這個繼承有點深,慢慢來,最終爸爸肯定是ImageView,但每個繼承做了深度定制

  private static Supplier<? extends SimpleDraweeControllerBuilder> sDraweeControllerBuilderSupplier;// 這貨就是前面初始化進來的業(yè)務邏輯提供者

  /** Initializes {@link SimpleDraweeView} with supplier of Drawee controller builders. */
  public static void initialize( // 初始化傳值
      Supplier<? extends SimpleDraweeControllerBuilder> draweeControllerBuilderSupplier) {
    sDraweeControllerBuilderSupplier = draweeControllerBuilderSupplier;
  }

  /** Shuts {@link SimpleDraweeView} down. */
  public static void shutDown() { // 關閉
    sDraweeControllerBuilderSupplier = null;
  }

  private SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder; // 真正的業(yè)務邏輯對象,從sDraweeControllerBuilderSupplier拿出

  public SimpleDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
    super(context, hierarchy);
    init(context, null);
  }

  public SimpleDraweeView(Context context) {
    super(context);
    init(context, null);
  }

  public SimpleDraweeView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
  }

  public SimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context, attrs);
  }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public SimpleDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init(context, attrs);
  }

  private void init(Context context, @Nullable AttributeSet attrs) {
    if (isInEditMode()) { // 來自view,是否控件可以編輯
      return;
    }
    Preconditions.checkNotNull(
        sDraweeControllerBuilderSupplier,
        "SimpleDraweeView was not initialized!"); // 檢查sDraweeControllerBuilderSupplier
    mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get(); // 拿到對應的業(yè)務邏輯(正常來說都是PipelineDraweeControllerBuilder,如果自己沒有外部定制需求)

    // 拿布局屬性,基本無用,可以是個默認圖uri
    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);
        }
      } finally {
        gdhAttrs.recycle();
      }
    }
  }

  protected SimpleDraweeControllerBuilder getControllerBuilder() { // 給外部使用,沒有什么好說的
    return mSimpleDraweeControllerBuilder;
  }

  /**
   * Displays an image given by the uri.
   *
   * @param uri uri of the image
   * @undeprecate
   */
  @Override
  public void setImageURI(Uri uri) { // 定制網絡圖片url
    setImageURI(uri, null);
  }

  /**
   * Displays an image given by the uri string.
   *
   * @param uriString uri string of the image
   */
  public void setImageURI(@Nullable String uriString) {
    setImageURI(uriString, null);
  }

  /**
   * Displays an image given by the uri.
   *
   * @param uri uri of the image
   * @param callerContext caller context
   */
  public void setImageURI(Uri uri, @Nullable Object callerContext) { // builder模式建立DraweeController 
    DraweeController controller = mSimpleDraweeControllerBuilder
        .setCallerContext(callerContext)// 這貨如果沒有指定,都是null,一直傳到所有的生產者中
        .setUri(uri)
        .setOldController(getController())// 這貨首次是null
        .build();
    setController(controller);
  }

  /**
   * Displays an image given by the uri string.
   *
   * @param uriString uri string of the image
   * @param callerContext caller context
   */
  public void setImageURI(@Nullable String uriString, @Nullable Object callerContext) { // 多態(tài)
    Uri uri = (uriString != null) ? Uri.parse(uriString) : null;
    setImageURI(uri, callerContext);
  }
}
SimpleDraweeView 的繼承先不看,控件處理而已,先看完關心request流程。

流程:SimpleDraweeView.setImageURI() ===> PipelineDraweeControllerBuilder.build(),然后SimpleDraweeView 再持有PipelineDraweeController這個對象

接著看注釋,這個build類:

package com.facebook.drawee.backends.pipeline;

import *

/**
 * Concrete implementation of ImagePipeline Drawee controller builder. (業(yè)務邏輯實現類)
 * <p/> See {@link AbstractDraweeControllerBuilder} for more details.
 */
public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
    PipelineDraweeControllerBuilder,
    ImageRequest,
    CloseableReference<CloseableImage>,
    ImageInfo> { // 很多實現在基類AbstractDraweeControllerBuilder完成,如果你需要定制自己DraweeController,繼承這個基類

  private final ImagePipeline mImagePipeline; // 各種緩存和策略,維護臟活的就是它
  private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;// 這貨持有uiThread,用來回掉更新,配合ImagePipeline 完成請求

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

  @Override
  public PipelineDraweeControllerBuilder setUri(Uri uri) { // 轉換成一個ImageRequest
    return super.setImageRequest(ImageRequest.fromUri(uri));
  }

  @Override
  public PipelineDraweeControllerBuilder setUri(@Nullable String uriString) { // 轉換成一個ImageRequest
    return super.setImageRequest(ImageRequest.fromUri(uriString));
  }

// 這個函數來自SimpleDraweeView:setImageURI():PipelineDraweeControllerBuilder.build()
  @Override
  protected PipelineDraweeController obtainController() { // 父類會回掉,首次會走else,為了重復使用,把新數據更新到controller中
    DraweeController oldController = getOldController(); 
    PipelineDraweeController controller;
    if (oldController instanceof PipelineDraweeController) {
      controller = (PipelineDraweeController) oldController;
      controller.initialize(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext());
    } else {
      controller = mPipelineDraweeControllerFactory.newController(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext());
    }
    return controller;
  }

  private CacheKey getCacheKey() { // 根據imageRequest 拿到對應的Cache策略,這貨從ImagePipeline 拿到Cache
    final ImageRequest imageRequest = getImageRequest();
    final CacheKeyFactory cacheKeyFactory = mImagePipeline.getCacheKeyFactory();
    CacheKey cacheKey = null;
    if (cacheKeyFactory != null && imageRequest != null) {
      if (imageRequest.getPostprocessor() != null) {
        cacheKey = cacheKeyFactory.getPostprocessedBitmapCacheKey(
            imageRequest,
            getCallerContext());
      } else {
        cacheKey = cacheKeyFactory.getBitmapCacheKey(
            imageRequest,
            getCallerContext());
      }
    }
    return cacheKey;
  }

 // 數據Bean,帶有回掉數據接口(成功或者失敗),利用執(zhí)行ImagePipeline request
  @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);
    }
  }
    
    .......
}
好了大致知道了Cache類和Executor類了,都來自ImagePipeline。
ImagePipeline 負責圖片的獲取和管理。圖片可以來自遠程服務器,本地文件,或者Content Provider,本地資源。壓縮后的文件緩存在本地存儲中,Bitmap數據緩存在內存中。
obtainController(),這個函數比較重要,構造了業(yè)務邏輯,有點像MVC,這里創(chuàng)建后生成回掉,給后面view,addWindow()后,收集WMS和IMS(WindowManagerService和InputeManagerService)產生的生命周期回掉或者輸入事件綁定。

在5.0系統以下,Image Pipeline 使用 pinned purgeables 將Bitmap數據避開Java堆內存,存在ashmem中。這要求圖片不使用時,要顯式地釋放內存。
SimpleDraweeView自動處理了這個釋放過程,所以沒有特殊情況,盡量使用SimpleDraweeView,在特殊的場合,如果有需要,也可以直接控制Image Pipeline。

Paste_Image.png

ImagePipeline介紹來自
關于ImagePipeline后面文章介紹里面策略和緩存詳細,先看主request

那執(zhí)行Requst代碼在哪,在前面SimpleDraweeView.setImageURI()里面是執(zhí)行

package com.facebook.drawee.backends.pipeline;

import *

/**
 * 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. The data
 * source is automatically obtained and closed based on attach / detach calls.
 */
public class PipelineDraweeController
    extends AbstractDraweeController<CloseableReference<CloseableImage>, ImageInfo> {

  // Components
  private final Resources mResources;
  private final AnimatedDrawableFactory mAnimatedDrawableFactory;

  private @Nullable MemoryCache<CacheKey, CloseableImage> mMemoryCache;

  private static Experiment sExperiment; // 這貨相當于一個對象鎖

  private CacheKey mCacheKey;

  // Constant state (non-final because controllers can be reused)
  private Supplier<DataSource<CloseableReference<CloseableImage>>> mDataSourceSupplier;

  public PipelineDraweeController( // 初始化和傳值一堆,為了基類使用
      Resources resources,
      DeferredReleaser deferredReleaser,
      AnimatedDrawableFactory animatedDrawableFactory,
      Executor uiThreadExecutor,
      MemoryCache<CacheKey, CloseableImage> memoryCache,
      Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext) {
      super(deferredReleaser, uiThreadExecutor, id, callerContext);
    mResources = resources;
    mAnimatedDrawableFactory = animatedDrawableFactory;
    mMemoryCache = memoryCache;
    mCacheKey = cacheKey;
    init(dataSourceSupplier);
  }

  public void initialize(
      Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext) {
    super.initialize(id, callerContext);
    init(dataSourceSupplier);
    mCacheKey = cacheKey;
  }

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

// 這個函數比較重要,利用DataSourceSupplier提供model接口數據接口(MVC模式)
  @Override
  protected DataSource<CloseableReference<CloseableImage>> getDataSource() { // 更新數據的接口,有成功和失敗
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this));
    }
    return mDataSourceSupplier.get();
  }

  @Override
  protected Drawable createDrawable(CloseableReference<CloseableImage> image) {// 創(chuàng)建Drawable的策略回掉
    Preconditions.checkState(CloseableReference.isValid(image));
    CloseableImage closeableImage = image.get();
    if (closeableImage instanceof CloseableStaticBitmap) {
      CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) closeableImage;
      Drawable bitmapDrawable = new BitmapDrawable(
        mResources,
        closeableStaticBitmap.getUnderlyingBitmap());
      if (closeableStaticBitmap.getRotationAngle() == 0 ||
          closeableStaticBitmap.getRotationAngle() == EncodedImage.UNKNOWN_ROTATION_ANGLE) {
        return bitmapDrawable;
      } else {
        return new OrientedDrawable(bitmapDrawable, closeableStaticBitmap.getRotationAngle());
      }
    } else if (mAnimatedDrawableFactory != null) {
      return mAnimatedDrawableFactory.create(closeableImage);
    } else {
      throw new UnsupportedOperationException("Unrecognized image class: " + closeableImage);
    }
  }
       .......

  @Override
  protected void releaseImage(@Nullable CloseableReference<CloseableImage> image) { // 釋放引用策略
    CloseableReference.closeSafely(image);
  }

  @Override
  protected void releaseDrawable(@Nullable Drawable drawable) { // 釋放引用策略
    if (drawable instanceof DrawableWithCaches) {
      ((DrawableWithCaches) drawable).dropCaches();
    }
  }

  @Override 
  protected CloseableReference<CloseableImage> getCachedImage() { // 關閉引用策略
    if (!getExperiment().mIsFastCheckEnabled) {
      return null;
    }
    if (mMemoryCache == null || mCacheKey == null) {
      return null;
    }
    // We get the CacheKey
    CloseableReference<CloseableImage> closeableImage = mMemoryCache.get(mCacheKey);
    if (closeableImage != null && !closeableImage.get().getQualityInfo().isOfFullQuality()) {
      closeableImage.close();
      return null;
    }
    return closeableImage;
  }

  /**
   * @return The Experiment object
   */
  protected static Experiment getExperiment() {
    if (sExperiment == null) {
      sExperiment = new Experiment();
    }
    return sExperiment;
  }

  protected static class Experiment { // 檢查類

    private boolean mIsFastCheckEnabled;

    public Experiment setFastCheckEnabled(final boolean fastCheckEnabled) {
      mIsFastCheckEnabled = fastCheckEnabled;
      return this;
    }
  }
}

上面只是實力類,真正調用在基類, 比較重要的就是getDataSource()和createDrawable()的實現了,其它都是釋放資源和回收,后面再講這個資源回收和回掉過程

接下來看基類指明干活


package com.facebook.drawee.controller;

import *

/**
 * Abstract Drawee controller that implements common functionality
 * regardless of the backend used to fetch the image.
 *
 * All methods should be called on the main UI thread.
 *
 */
@NotThreadSafe
public abstract class AbstractDraweeController<T, INFO> implements
    DraweeController,
    DeferredReleaser.Releasable,
    GestureDetector.ClickListener {

  /**
   * This class is used to allow an optimization of not creating a ForwardingControllerListener
   * when there is only a single controller listener.
   * 這貨也比較重要,但尼瑪你沒有定制自己controllistener,默認為null,沒有什么卵用
   */
  private static class InternalForwardingListener<INFO> extends ForwardingControllerListener<INFO> { 
    public static <INFO> InternalForwardingListener<INFO> createInternal(
        ControllerListener<? super INFO> listener1,
        ControllerListener<? super INFO> listener2) {
      InternalForwardingListener<INFO> forwarder = new InternalForwardingListener<INFO>();
      forwarder.addListener(listener1);
      forwarder.addListener(listener2);
      return forwarder;
    }
  }

  // Components
  private final DraweeEventTracker mEventTracker = DraweeEventTracker.newInstance(); // 日志追蹤
  private final DeferredReleaser mDeferredReleaser; // 賴加載,延遲安排任務
  private final Executor mUiThreadImmediateExecutor; // ui線程從PipelineDraweeControllerBuilder :PipelineDraweeControllerFactory 來的

  // Optional components
  private @Nullable RetryManager mRetryManager; // 重試機制
  private @Nullable GestureDetector mGestureDetector; // 手勢
  private @Nullable ControllerListener<INFO> mControllerListener; // 業(yè)務邏輯回掉監(jiān)聽

  // Hierarchy
  private @Nullable SettableDraweeHierarchy mSettableDraweeHierarchy; // view對象樹, 用于組織和維護最終繪制和呈現的 Drawable 對象
  private @Nullable Drawable mControllerOverlay; // view對象

  // Constant state (non-final because controllers can be reused)
  private String mId;
  private Object mCallerContext;

  // Mutable state
  private boolean mIsAttached; // 是否view添加到window上
  private boolean mIsRequestSubmitted; // 是否已經開始request
  private boolean mHasFetchFailed;// 當前request更新失敗flag
  private boolean mRetainImageOnFailure;// 設置是否顯示最新的可用的圖片(默認圖),在失敗的時候
  private @Nullable String mContentDescription; // 描述
  private @Nullable DataSource<T> mDataSource; // 子類data策略
  private @Nullable T mFetchedImage; // 獲取到當前image
  private @Nullable Drawable mDrawable; // 圖片資源

  public AbstractDraweeController(
      DeferredReleaser deferredReleaser,
      Executor uiThreadImmediateExecutor,
      String id,
      Object callerContext) {
    mDeferredReleaser = deferredReleaser;
    mUiThreadImmediateExecutor = uiThreadImmediateExecutor;
    init(id, callerContext, true);
  }

  protected void initialize(String id, Object callerContext) {
    init(id, callerContext, false);
  }

  private void init(String id, Object callerContext, boolean justConstructed) {
    mEventTracker.recordEvent(Event.ON_INIT_CONTROLLER);
    // cancel deferred release
    if (!justConstructed && mDeferredReleaser != null) {
      mDeferredReleaser.cancelDeferredRelease(this);
    }
    // reinitialize mutable state (fetch state)
    mIsAttached = false;
    releaseFetch();
    mRetainImageOnFailure = false;
    // reinitialize optional components
    if (mRetryManager != null) {
      mRetryManager.init();
    }
    if (mGestureDetector != null) {
      mGestureDetector.init();
      mGestureDetector.setClickListener(this);
    }
    if (mControllerListener instanceof InternalForwardingListener) {
      ((InternalForwardingListener) mControllerListener).clearListeners();
    } else {
      mControllerListener = null;
    }
    // clear hierarchy and controller overlay
    if (mSettableDraweeHierarchy != null) {
      mSettableDraweeHierarchy.reset();
      mSettableDraweeHierarchy.setControllerOverlay(null);
      mSettableDraweeHierarchy = null;
    }
    mControllerOverlay = null;
    // reinitialize constant state
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x %s -> %s: initialize", System.identityHashCode(this), mId, id);
    }
    mId = id;
    mCallerContext = callerContext;
  }

  @Override
  public void release() {
    mEventTracker.recordEvent(Event.ON_RELEASE_CONTROLLER);
    if (mRetryManager != null) {
      mRetryManager.reset();
    }
    if (mGestureDetector != null) {
      mGestureDetector.reset();
    }
    if (mSettableDraweeHierarchy != null) {
      mSettableDraweeHierarchy.reset();
    }
    releaseFetch();
  }

  private void releaseFetch() { // 釋放hold的image和data,為request做準備
    boolean wasRequestSubmitted = mIsRequestSubmitted;
    mIsRequestSubmitted = false;
    mHasFetchFailed = false;
    if (mDataSource != null) {
      mDataSource.close();
      mDataSource = null;
    }
    if (mDrawable != null) {
      releaseDrawable(mDrawable);
    }
    if (mContentDescription != null) {
      mContentDescription = null;
    }
    mDrawable = null;
    if (mFetchedImage != null) {
      logMessageAndImage("release", mFetchedImage);
      releaseImage(mFetchedImage);
      mFetchedImage = null;
    }
    if (wasRequestSubmitted) {
      getControllerListener().onRelease(mId);
    }
  }

  public Object getCallerContext() { // 默認情況都是null,基本無卵用,如果你有特殊要求,這個上下文能起到很大重要,如,日志追蹤
    return mCallerContext;
  }

  protected @Nullable RetryManager getRetryManager() { // 重試機制
    return mRetryManager;
  }

      .......

  /** Gets gesture detector. */
  protected @Nullable GestureDetector getGestureDetector() {
    return mGestureDetector;
  }

  /** Sets gesture detector. */
  protected void setGestureDetector(@Nullable GestureDetector gestureDetector) {
    mGestureDetector = gestureDetector;
    if (mGestureDetector != null) {
      mGestureDetector.setClickListener(this);
    }
  }

// 這貨有意思了,這貨給你個flag,需要set進來,作用是你下載完后,失敗需要重新下載標志
  protected void setRetainImageOnFailure(boolean enabled) {
    mRetainImageOnFailure = enabled;
  }

      .......

 // 基本無用,默認是null,為了完成你自己定制的回掉監(jiān)聽設置
  /** Adds controller listener. */
  public void addControllerListener(ControllerListener<? super INFO> controllerListener) {
    Preconditions.checkNotNull(controllerListener);
    if (mControllerListener instanceof InternalForwardingListener) {
      ((InternalForwardingListener<INFO>) mControllerListener).addListener(controllerListener);
      return;
    }
    if (mControllerListener != null) {
      mControllerListener = InternalForwardingListener.createInternal(
          mControllerListener,
          controllerListener);
      return;
    }
    // Listener only receives <INFO>, it never produces one.
    // That means if it can accept <? super INFO>, it can very well accept <INFO>.
    mControllerListener = (ControllerListener<INFO>) controllerListener;
  }

      .......

  /** Gets controller listener for internal use. */
  protected ControllerListener<INFO> getControllerListener() {
    if (mControllerListener == null) {
      return BaseControllerListener.getNoOpListener();
    }
    return mControllerListener;
  }

  /** Gets the hierarchy */
  @Override
  public @Nullable
  DraweeHierarchy getHierarchy() {
    return mSettableDraweeHierarchy;
  }

  // 這函數比較屌,維護view樹,以后再講
  @Override
  public void setHierarchy(@Nullable DraweeHierarchy hierarchy) {
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(
          TAG,
          "controller %x %s: setHierarchy: %s",
          System.identityHashCode(this),
          mId,
          hierarchy);
    }
    mEventTracker.recordEvent(
        (hierarchy != null) ? Event.ON_SET_HIERARCHY : Event.ON_CLEAR_HIERARCHY);
    // force release in case request was submitted
    if (mIsRequestSubmitted) {
      mDeferredReleaser.cancelDeferredRelease(this);
      release();
    }
    // clear the existing hierarchy
    if (mSettableDraweeHierarchy != null) {
      mSettableDraweeHierarchy.setControllerOverlay(null);
      mSettableDraweeHierarchy = null;
    }
    // set the new hierarchy
    if (hierarchy != null) {
      Preconditions.checkArgument(hierarchy instanceof SettableDraweeHierarchy);
      mSettableDraweeHierarchy = (SettableDraweeHierarchy) hierarchy;
      mSettableDraweeHierarchy.setControllerOverlay(mControllerOverlay);
    }
  }

  /** Sets the controller overlay */
  protected void setControllerOverlay(@Nullable Drawable controllerOverlay) {
    mControllerOverlay = controllerOverlay;
    if (mSettableDraweeHierarchy != null) {
      mSettableDraweeHierarchy.setControllerOverlay(mControllerOverlay);
    }
  }

  /** Gets the controller overlay */
  protected @Nullable Drawable getControllerOverlay() {
    return mControllerOverlay;
  }

  @Override
  public void onAttach() { // 回調
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(
          TAG,
          "controller %x %s: onAttach: %s",
          System.identityHashCode(this),
          mId,
          mIsRequestSubmitted ? "request already submitted" : "request needs submit");
    }
    mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
    Preconditions.checkNotNull(mSettableDraweeHierarchy);
    mDeferredReleaser.cancelDeferredRelease(this);
    mIsAttached = true;
    if (!mIsRequestSubmitted) {
      submitRequest();
    }
  }

  @Override
  public void onDetach() { // 回調
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x %s: onDetach", System.identityHashCode(this), mId);
    }
    mEventTracker.recordEvent(Event.ON_DETACH_CONTROLLER);
    mIsAttached = false;
    mDeferredReleaser.scheduleDeferredRelease(this);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) { // 回調
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x %s: onTouchEvent %s", System.identityHashCode(this), mId, event);
    }
    if (mGestureDetector == null) {
      return false;
    }
    if (mGestureDetector.isCapturingGesture() || shouldHandleGesture()) {
      mGestureDetector.onTouchEvent(event);
      return true;
    }
    return false;
  }

  /** Returns whether the gesture should be handled by the controller */
  protected boolean shouldHandleGesture() {
    return shouldRetryOnTap();
  }

  private boolean shouldRetryOnTap() {
    // We should only handle touch event if we are expecting some gesture.
    // For example, we expect click when fetch fails and tap-to-retry is enabled.
    return mHasFetchFailed && mRetryManager != null && mRetryManager.shouldRetryOnTap(); // shouldRetryOnTap 判斷是否超過重新的最大值(MAX:4次)
  }

  @Override
  public boolean onClick() {// 回調
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x %s: onClick", System.identityHashCode(this), mId);
    }
    if (shouldRetryOnTap()) { // mRetryManager去通知重新request準備
      mRetryManager.notifyTapToRetry();
      mSettableDraweeHierarchy.reset();
      submitRequest();
      return true;
    }
    return false;
  }

  protected void submitRequest() { // 這貨就是干活的
    final T closeableImage = getCachedImage(); // 拿到子類的Cache圖片
    if (closeableImage != null) { // 如果有,直接刷新成功
      mDataSource = null;
      mIsRequestSubmitted = true;
      mHasFetchFailed = false;
      mEventTracker.recordEvent(Event.ON_SUBMIT_CACHE_HIT);
      getControllerListener().onSubmit(mId, mCallerContext);
      onNewResultInternal(mId, mDataSource, closeableImage, 1.0f, true, true);
      return;
    }
    mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT); // 日志
    getControllerListener().onSubmit(mId, mCallerContext); // 給監(jiān)聽器去干活,一個id一個坑
    mSettableDraweeHierarchy.setProgress(0, true);// 對象樹準備
    mIsRequestSubmitted = true;// 已經提交
    mHasFetchFailed = false;// 重置
    mDataSource = getDataSource(); // 獲取子類data策略
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(
          TAG,
          "controller %x %s: submitRequest: dataSource: %x",
          System.identityHashCode(this),
          mId,
          System.identityHashCode(mDataSource));
    }
    final String id = mId;
    final boolean wasImmediate = mDataSource.hasResult();
    final DataSubscriber<T> dataSubscriber =
        new BaseDataSubscriber<T>() {
          @Override
          public void onNewResultImpl(DataSource<T> dataSource) {
            // isFinished must be obtained before image, otherwise we might set intermediate result
            // as final image.
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            T image = dataSource.getResult();
            if (image != null) {
              onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
            } else if (isFinished) {
              onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
            }
          }
          @Override
          public void onFailureImpl(DataSource<T> dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource<T> dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }
        };
    mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor); // 在ui線程訂閱,開始刷新
  }

  private void onNewResultInternal( // 成功
      String id,
      DataSource<T> dataSource,
      @Nullable T image,
      float progress,
      boolean isFinished,
      boolean wasImmediate) {
    // ignore late callbacks (data source that returned the new result is not the one we expected)
    if (!isExpectedDataSource(id, dataSource)) { // 略過老data
      logMessageAndImage("ignore_old_datasource @ onNewResult", image);
      releaseImage(image);
      dataSource.close();
      return;
    }
    mEventTracker.recordEvent( // 日志追蹤
        isFinished ? Event.ON_DATASOURCE_RESULT : Event.ON_DATASOURCE_RESULT_INT);
    // create drawable
    Drawable drawable;
    try {
      drawable = createDrawable(image); //調用子類策略創(chuàng)建drawable 
    } catch (Exception exception) { // 失敗打印和釋放資源
      logMessageAndImage("drawable_failed @ onNewResult", image);
      releaseImage(image);
      onFailureInternal(id, dataSource, exception, isFinished);
      return;
    }
    T previousImage = mFetchedImage; // 完成新老數據交換
    Drawable previousDrawable = mDrawable;
    mFetchedImage = image; // 給hold的當前image進行策略釋放
    mDrawable = drawable;
    try {
      // set the new image
      if (isFinished) { // 完成后,刷新,監(jiān)聽回掉,改干嘛干嘛
        logMessageAndImage("set_final_result @ onNewResult", image);
        mDataSource = null;
        mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);
        getControllerListener().onFinalImageSet(id, getImageInfo(image), getAnimatable());
        // IMPORTANT: do not execute any instance-specific code after this point
      } else {
        logMessageAndImage("set_intermediate_result @ onNewResult", image);
        mSettableDraweeHierarchy.setImage(drawable, progress, wasImmediate);
        getControllerListener().onIntermediateImageSet(id, getImageInfo(image));
        // IMPORTANT: do not execute any instance-specific code after this point
      }
    } finally { // 釋放當前請求資源
      if (previousDrawable != null && previousDrawable != drawable) {
        releaseDrawable(previousDrawable);
      }
      if (previousImage != null && previousImage != image) {
        logMessageAndImage("release_previous_result @ onNewResult", previousImage);
        releaseImage(previousImage);
      }
    }
  }

  private void onFailureInternal( // 更新失敗數據
      String id,
      DataSource<T> dataSource,
      Throwable throwable,
      boolean isFinished) {
    // ignore late callbacks (data source that failed is not the one we expected)
    if (!isExpectedDataSource(id, dataSource)) { // 判斷是否是自己感興趣的data
      logMessageAndFailure("ignore_old_datasource @ onFailure", throwable);
      dataSource.close();
      return;
    }
    mEventTracker.recordEvent( // 日志追蹤
        isFinished ? Event.ON_DATASOURCE_FAILURE : Event.ON_DATASOURCE_FAILURE_INT);
    // fail only if the data source is finished
    if (isFinished) { //刷新失敗流程
      logMessageAndFailure("final_failed @ onFailure", throwable);
      mDataSource = null;
      mHasFetchFailed = true;
      // Set the previously available image if available.
      if (mRetainImageOnFailure && mDrawable != null) {
        mSettableDraweeHierarchy.setImage(mDrawable, 1f, true);
      } else if (shouldRetryOnTap()) {
        mSettableDraweeHierarchy.setRetry(throwable);
      } else {
        mSettableDraweeHierarchy.setFailure(throwable);
      }
      getControllerListener().onFailure(mId, throwable);
      // IMPORTANT: do not execute any instance-specific code after this point
    } else {
      logMessageAndFailure("intermediate_failed @ onFailure", throwable);
      getControllerListener().onIntermediateImageFailed(mId, throwable);
      // IMPORTANT: do not execute any instance-specific code after this point
    }
  }

  private void onProgressUpdateInternal( // 更新實時數據
      String id,
      DataSource<T> dataSource,
      float progress,
      boolean isFinished) {
    // ignore late callbacks (data source that failed is not the one we expected)
    if (!isExpectedDataSource(id, dataSource)) {
      logMessageAndFailure("ignore_old_datasource @ onProgress", null);
      dataSource.close();
      return;
    }
    if (!isFinished) {
      mSettableDraweeHierarchy.setProgress(progress, false);
    }
  }

  private boolean isExpectedDataSource(String id, DataSource<T> dataSource) { // 判斷當前提交狀態(tài)的dataSource 釋放為新的,持有id老dataSource 不再感興趣
    if (dataSource == null && mDataSource == null) {
      // DataSource is null when we use directly the Bitmap from the MemoryCache. In this case
      // we don't have to close the DataSource.
      return true;
    }
    // There are several situations in which an old data source might return a result that we are no
    // longer interested in. To verify that the result is indeed expected, we check several things:
    return id.equals(mId) && dataSource == mDataSource && mIsRequestSubmitted;
  }

     ........

  @Override
  public @Nullable Animatable getAnimatable() {
    return (mDrawable instanceof Animatable) ? (Animatable) mDrawable : null;
  }

 // 下面都是回掉子類接口 PipelineDraweeController

  protected abstract DataSource<T> getDataSource();

  protected abstract Drawable createDrawable(T image);

  protected abstract @Nullable INFO getImageInfo(T image);

  protected String getImageClass(@Nullable T image) {
    return (image != null) ? image.getClass().getSimpleName() : "<null>";
  }

  protected int getImageHash(@Nullable T image) {
    return System.identityHashCode(image);
  }

  protected abstract void releaseImage(@Nullable T image);

  protected abstract void releaseDrawable(@Nullable Drawable drawable);

     ........

}

屬性:SettableDraweeHierarchy 你可以認為這貨就是你的drawable的修飾類所需要維護的樹形結構,相當于drawable是衣服的話,DraweeHierarchy就是衣服上的線條結構和底色配色,和XML中布局默認屬性差不多

這個類比較長,所有request是從attach開始submit,onDetach停止和釋放資源維護。

attach和onDetach事件來自于DraweeHierarchy中toplevel,Drawable的DraweeHold,它實現了監(jiān)聽和派發(fā)回掉

好了你大致也看懂了submit這個函數中,先準備一些flag,然后給Listener去實現submit,然后自己訂閱回掉在ui線程,開始刷新界面。

這個大多數人都有個誤區(qū),認為Listener是實現提交請求,其實不是,這貨只是監(jiān)聽回調,真正在跑網絡數據得是這個訂閱得datasrouce,而這個datasrouce來自getDataSource(),這個來自AbstractDraweeControllerBuilder:getDataSourceSupplierForRequest(),一路追蹤最后來自PipelineDraweeControllerBuilder:getDataSourceForRequest(),好了這個主線來了,ImagePipeline要開始干活了,往上面翻,自己再總結理解下。

接著看:Fresco源碼分析(二)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容