Fresco源码分析(一)

作者: TragedyGo | 来源:发表于2017-01-15 17:36 被阅读1163次

    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; //业务逻辑工厂
    
      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(); // 给外部需求所用,拿到一个新的业务逻辑工厂对象
      }
    
      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();

    请继续看我的注释:

    /*
     * 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;// 这货就是前面初始化进来的业务逻辑提供者
    
      /** 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; // 真正的业务逻辑对象,从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(); // 拿到对应的业务逻辑(正常来说都是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) { // 多态
        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. (业务逻辑实现类)
     * <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,带有回掉数据接口(成功或者失败),利用执行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(),这个函数比较重要,构造了业务逻辑,有点像MVC,这里创建后生成回掉,给后面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
    那执行Requst代码在哪,在前面SimpleDraweeView.setImageURI()里面是执行
    
    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) {// 创建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; // 业务逻辑回掉监听
    
      // 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,为了完成你自己定制的回掉监听设置
      /** 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); // 给监听器去干活,一个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); //调用子类策略创建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) { // 完成后,刷新,监听回掉,改干嘛干嘛
            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) { // 判断当前提交状态的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,它实现了监听和派发回掉

    好了你大致也看懂了submit这个函数中,先准备一些flag,然后给Listener去实现submit,然后自己订阅回掉在ui线程,开始刷新界面。

    这个大多数人都有个误区,认为Listener是实现提交请求,其实不是,这货只是监听回调,真正在跑网络数据得是这个订阅得datasrouce,而这个datasrouce来自getDataSource(),这个来自AbstractDraweeControllerBuilder:getDataSourceSupplierForRequest(),一路追踪最后来自PipelineDraweeControllerBuilder:getDataSourceForRequest(),好了这个主线来了,ImagePipeline要开始干活了,往上面翻,自己再总结理解下。

    接着看:Fresco源码分析(二)

    相关文章

      网友评论

        本文标题:Fresco源码分析(一)

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