Fresco图片加载源码浅析

前言

Fresco 中设计有一个叫做 image pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。

Fresco 中设计有一个叫做 Drawees 模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。

使用

Fresco使用:

首先需要在layout布局上使用fresco的simpleDraweeView:


然后再java代码中使用:

    SimpleDraweeView simpleDraweeView = findViewById(R.id.simpleDraweeView);
    Uri uri = Uri.parse("https://www.baidu.com/img/xinshouye_034fec51df225fe8410f36ad3f2fccf6.png");
    simpleDraweeView.setImageURI(uri);

由上述使用方法可以看出,只需要给定一个容器然后传入一个url地址,即可完成对图片的加载;那么它的内部运行流程是什么样的呢?

fresco整个业务流程:

E:\我的图片\20160523111021635.png

入口

很明显,SimpleDraweeView是我们先要弄清楚的,首先要明白它是继承自ImageView的,并且具有layout布局,显然是自定义View,第一步必然是从布局文件样式中读取属性值。

那么我们直接看看simpleDraweeView.setImageURI(uri)方法:

public void setImageURI(Uri uri, @Nullable Object callerContext) {
    DraweeController controller = mSimpleDraweeControllerBuilder
        .setCallerContext(callerContext)
        .setUri(uri)
        .setOldController(getController())
        .build();
    setController(controller);
  }

首先它创建了一个Controller并调用setController,看一下Controller是怎么创建的:

@Override
  public AbstractDraweeController build() {
    validate();
    //赋值图片请求
    // if only a low-res request is specified, treat it as a final request.
    if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) {
      mImageRequest = mLowResImageRequest;
      mLowResImageRequest = null;
    }
    //创建ontroller
    return buildController();
  }

protected AbstractDraweeController buildController() {
    AbstractDraweeController controller = obtainController();//获取请求
    controller.setRetainImageOnFailure(getRetainImageOnFailure());
    controller.setContentDescription(getContentDescription());
    controller.setControllerViewportVisibilityListener(getControllerViewportVisibilityListener());
    maybeBuildAndSetRetryManager(controller);
    maybeAttachListeners(controller);
    return controller;
  }


@Override
  protected PipelineDraweeController obtainController() {
    DraweeController oldController = getOldController();
    PipelineDraweeController controller;
    if (oldController instanceof PipelineDraweeController) {
      controller = (PipelineDraweeController) oldController;
      controller.initialize(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext(),
          mCustomDrawableFactories);
    } else {
        //工厂模式创建Controller
      controller = mPipelineDraweeControllerFactory.newController(
          obtainDataSourceSupplier(),
          generateUniqueControllerId(),
          getCacheKey(),
          getCallerContext(),
          mCustomDrawableFactories);
    }
    return controller;
  }


public PipelineDraweeController newController(
      Supplier>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext,
      @Nullable ImmutableList 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
    //创建Controller
    PipelineDraweeController controller = internalCreateController(
        mResources,
        mDeferredReleaser,
        mAnimatedDrawableFactory,
        mUiThreadExecutor,
        mMemoryCache,
        mDrawableFactories,
        customDrawableFactories,
        dataSourceSupplier,
        id,
        cacheKey,
        callerContext);
    if (mDebugOverlayEnabledSupplier != null) {
      controller.setDrawDebugOverlay(mDebugOverlayEnabledSupplier.get());
    }
    return controller;
  }

protected PipelineDraweeController internalCreateController(
      Resources resources,
      DeferredReleaser deferredReleaser,
      DrawableFactory animatedDrawableFactory,
      Executor uiThreadExecutor,
      MemoryCache memoryCache,
      @Nullable ImmutableList globalDrawableFactories,
      @Nullable ImmutableList customDrawableFactories,
      Supplier>> dataSourceSupplier,
      String id,
      CacheKey cacheKey,
      Object callerContext) {
    //至此Controller创建完毕 为PipelineDraweeController实例
    PipelineDraweeController controller = new PipelineDraweeController(
        resources,
        deferredReleaser,
        animatedDrawableFactory,
        uiThreadExecutor,
        memoryCache,
        dataSourceSupplier,
        id,
        cacheKey,
        callerContext,
        globalDrawableFactories);
    controller.setCustomDrawableFactories(customDrawableFactories);
    return controller;
  }

接下来,让我们看一看setController方法:

/** Sets the controller. */
  public void setController(@Nullable DraweeController draweeController) {
    mDraweeHolder.setController(draweeController);
    super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
  }

继续追踪mDraweeHolder.setController(draweeController):

public void setController(@Nullable DraweeController draweeController) {
    boolean wasAttached = mIsControllerAttached;
    if (wasAttached) {
      detachController();
    }

    // Clear the old controller
    if (isControllerValid()) {
      mEventTracker.recordEvent(Event.ON_CLEAR_OLD_CONTROLLER);
      mController.setHierarchy(null);
    }
    mController = draweeController;
    if (mController != null) {
      mEventTracker.recordEvent(Event.ON_SET_CONTROLLER);
      mController.setHierarchy(mHierarchy);
    } else {
      mEventTracker.recordEvent(Event.ON_CLEAR_CONTROLLER);
    }

    if (wasAttached) {
      attachController();
    }
  }

将draweeController赋值给mController,然后调用attachController方法:

private void attachController() {
    if (mIsControllerAttached) {
      return;
    }
    mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
    mIsControllerAttached = true;
    if (mController != null &&
        mController.getHierarchy() != null) {
      mController.onAttach();
    }
  }

继续追踪onAttach方法:

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();//提交数据请求
    }
  }

终于看到提交数据请求了:

protected void submitRequest() {
    //获取内存缓存
    final T closeableImage = getCachedImage();
    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);
    mSettableDraweeHierarchy.setProgress(0, true);
    mIsRequestSubmitted = true;
    mHasFetchFailed = false;
    //获取数据~~~    
    mDataSource = getDataSource();
    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 dataSubscriber =
        new BaseDataSubscriber() {
          @Override
          public void onNewResultImpl(DataSource 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 dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }
        };
    mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
  }

可以看到数据请求逻辑在getDataSource里面:

@Override
  protected DataSource> getDataSource() {
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this));
    }
    return mDataSourceSupplier.get();
  }

最终getDataSource将数据请求交给了mDataSourceSupplier.get(),那么mDataSourceSupplier是何方神圣呢?mDataSourceSupplier是什么时候初始化的呢?

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

我们发现,在创建controller的时候会传递obtainDataSourceSupplier方法为参数:

protected Supplier> obtainDataSourceSupplier() {
    if (mDataSourceSupplier != null) {
      return mDataSourceSupplier;
    }

    Supplier> supplier = null;

    // final image supplier;
    if (mImageRequest != null) {
        //获取网络数据提供者
      supplier = getDataSourceSupplierForRequest(mImageRequest);
    } else if (mMultiImageRequests != null) {
      supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests, mTryCacheOnlyFirst);
    }

    // increasing-quality supplier; highest-quality supplier goes first
    if (supplier != null && mLowResImageRequest != null) {
      List>> suppliers = new ArrayList<>(2);
      suppliers.add(supplier);
      suppliers.add(getDataSourceSupplierForRequest(mLowResImageRequest));
      supplier = IncreasingQualityDataSourceSupplier.create(suppliers);
    }

    // no image requests; use null data source supplier
    if (supplier == null) {
      supplier = DataSources.getFailedDataSourceSupplier(NO_REQUEST_EXCEPTION);
    }

    return supplier;
  }
/** Creates a data source supplier for the given image request. */
  protected Supplier> getDataSourceSupplierForRequest(
      final REQUEST imageRequest,
      final CacheLevel cacheLevel) {
    final Object callerContext = getCallerContext();
    return new Supplier>() {
      @Override
      public DataSource get() {
        return getDataSourceForRequest(imageRequest, callerContext, cacheLevel);
      }
      @Override
      public String toString() {
        return Objects.toStringHelper(this)
            .add("request", imageRequest.toString())
            .toString();
      }
    };
  }

至此mDataSourceSupplier才浮出水面,最后实现了get方法正是获取图片数据请求的方法:

@Override
  protected DataSource> getDataSourceForRequest(
      ImageRequest imageRequest,
      Object callerContext,
      CacheLevel cacheLevel) {
    return mImagePipeline.fetchDecodedImage(
        imageRequest,
        callerContext,
        convertCacheLevelToRequestLevel(cacheLevel));
  }

继续追踪:

public DataSource> fetchDecodedImage(
      ImageRequest imageRequest,
      Object callerContext,
      ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit) {
    try {
      Producer> producerSequence =
          mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
      return submitFetchRequest(
          producerSequence,
          imageRequest,
          lowestPermittedRequestLevelOnSubmit,
          callerContext);
    } catch (Exception exception) {
      return DataSources.immediateFailedDataSource(exception);
    }
  }

继续追踪submitFetchRequest:

private  DataSource> submitFetchRequest(
      Producer> producerSequence,
      ImageRequest imageRequest,
      ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
      Object callerContext) {
    final RequestListener requestListener = getRequestListenerForRequest(imageRequest);

    try {
      ImageRequest.RequestLevel lowestPermittedRequestLevel =
          ImageRequest.RequestLevel.getMax(
              imageRequest.getLowestPermittedRequestLevel(),
              lowestPermittedRequestLevelOnSubmit);
      SettableProducerContext settableProducerContext = new SettableProducerContext(
          imageRequest,
          generateUniqueFutureId(),
          requestListener,
          callerContext,
          lowestPermittedRequestLevel,
        /* isPrefetch */ false,
          imageRequest.getProgressiveRenderingEnabled() ||
              imageRequest.getMediaVariations() != null ||
              !UriUtil.isNetworkUri(imageRequest.getSourceUri()),
          imageRequest.getPriority());
      return CloseableProducerToDataSourceAdapter.create(
          producerSequence,
          settableProducerContext,
          requestListener);
    } catch (Exception exception) {
      return DataSources.immediateFailedDataSource(exception);
    }
  }

继续追踪CloseableProducerToDataSourceAdapter.create

public static  DataSource create(
      Producer producer,
      SettableProducerContext settableProducerContext,
      RequestListener listener) {
    return new ProducerToDataSourceAdapter(
        producer,
        settableProducerContext,
        listener);
  }

继续

protected AbstractProducerToDataSourceAdapter(
      Producer producer,
      SettableProducerContext settableProducerContext,
      RequestListener requestListener) {
    mSettableProducerContext = settableProducerContext;
    mRequestListener = requestListener;
    mRequestListener.onRequestStart(
        settableProducerContext.getImageRequest(),
        mSettableProducerContext.getCallerContext(),
        mSettableProducerContext.getId(),
        mSettableProducerContext.isPrefetch());
    producer.produceResults(createConsumer(), settableProducerContext);
  }

重点在producer.produceResults,但producer是什么呢?

public Producer>
  getNetworkFetchEncodedImageProducerSequence() {
    synchronized (this) {
      if (mNetworkEncodedImageProducerSequence == null) {
        mNetworkEncodedImageProducerSequence = new RemoveImageTransformMetaDataProducer(
            getBackgroundNetworkFetchToEncodedMemorySequence());
      }
    }
    return mNetworkEncodedImageProducerSequence;
  }

一直追踪,发现具体请求网络数据在NetworkFetchProducer这个类,其中有一个mNetworkFetcher.fetch方法:

@Override
  public void produceResults(Consumer consumer, ProducerContext context) {
    context.getListener()
        .onProducerStart(context.getId(), PRODUCER_NAME);
    final FetchState fetchState = mNetworkFetcher.createFetchState(consumer, context);
    mNetworkFetcher.fetch(
        fetchState, new NetworkFetcher.Callback() {
          @Override
          public void onResponse(InputStream response, int responseLength) throws IOException {
            NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
          }

          @Override
          public void onFailure(Throwable throwable) {
            NetworkFetchProducer.this.onFailure(fetchState, throwable);
          }

          @Override
          public void onCancellation() {
            NetworkFetchProducer.this.onCancellation(fetchState);
          }
        });
  }

看一下mNetworkFetcher.createFetchState方法做什么工作:

我们发现,有两个类实现了这个接口,分别是HttpUrlConnectionNetworkFetcher和OkHttpNetworkFetcher,走到这一步就很明显了:Fresco加载图片用的是okhttp和httpurlconnection。

让我们看一下Fresco的okhttp加载数据实现:

protected void fetchWithRequest(
      final OkHttpNetworkFetchState fetchState,
      final Callback callback,
      final Request request) {
    final Call call = mCallFactory.newCall(request);

    fetchState.getContext().addCallbacks(
        new BaseProducerContextCallbacks() {
          @Override
          public void onCancellationRequested() {
            if (Looper.myLooper() != Looper.getMainLooper()) {
              call.cancel();
            } else {
              mCancellationExecutor.execute(new Runnable() {
                @Override public void run() {
                  call.cancel();
                }
              });
            }
          }
        });

    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(Call call, Response response) throws IOException {
            fetchState.responseTime = SystemClock.elapsedRealtime();
            final ResponseBody body = response.body();
            try {
              if (!response.isSuccessful()) {
                handleException(
                    call,
                    new IOException("Unexpected HTTP code " + response),
                    callback);
                return;
              }

              BytesRange responseRange =
                  BytesRange.fromContentRangeHeader(response.header("Content-Range"));
              if (responseRange != null) {
                fetchState.setResponseBytesRange(responseRange);
                fetchState.setOnNewResultStatusFlags(Consumer.IS_PARTIAL_RESULT);
              }

              long contentLength = body.contentLength();
              if (contentLength < 0) {
                contentLength = 0;
              }
              callback.onResponse(body.byteStream(), (int) contentLength);
            } catch (Exception e) {
              handleException(call, e, callback);
            } finally {
              try {
                body.close();
              } catch (Exception e) {
                FLog.w(TAG, "Exception when closing response body", e);
              }
            }
          }

          @Override
          public void onFailure(Call call, IOException e) {
            handleException(call, e, callback);
          }
        });
  }

而Fresco的httpurlconnection实现:

void fetchSync(FetchState fetchState, Callback callback) {
    HttpURLConnection connection = null;
    InputStream is = null;
    try {
      connection = downloadFrom(fetchState.getUri(), MAX_REDIRECTS);

      if (connection != null) {
        is = connection.getInputStream();
        callback.onResponse(is, -1);
      }
    } catch (IOException e) {
      callback.onFailure(e);
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
          // do nothing and ignore the IOException here
        }
      }
      if (connection != null) {
        connection.disconnect();
      }
    }

  }

  private HttpURLConnection downloadFrom(Uri uri, int maxRedirects) throws IOException {
    HttpURLConnection connection = openConnectionTo(uri);
    int responseCode = connection.getResponseCode();

    if (isHttpSuccess(responseCode)) {
        return connection;

    } else if (isHttpRedirect(responseCode)) {
        String nextUriString = connection.getHeaderField("Location");
        connection.disconnect();

        Uri nextUri = (nextUriString == null) ? null : Uri.parse(nextUriString);
        String originalScheme = uri.getScheme();

        if (maxRedirects > 0 && nextUri != null && !nextUri.getScheme().equals(originalScheme)) {
          return downloadFrom(nextUri, maxRedirects - 1);
        } else {
          String message = maxRedirects == 0
              ? error("URL %s follows too many redirects", uri.toString())
              : error("URL %s returned %d without a valid redirect", uri.toString(), responseCode);
          throw new IOException(message);
        }

    } else {
        connection.disconnect();
        throw new IOException(String
            .format("Image URL %s returned HTTP code %d", uri.toString(), responseCode));
    }
  }

至此我们已经清楚,Fresco对图片的加载,那么他是怎么回调的呢?

可以看到

 mNetworkFetcher.fetch(
        fetchState, new NetworkFetcher.Callback() {
          @Override
          public void onResponse(InputStream response, int responseLength) throws IOException {
            NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
          }

          @Override
          public void onFailure(Throwable throwable) {
            NetworkFetchProducer.this.onFailure(fetchState, throwable);
          }

          @Override
          public void onCancellation() {
            NetworkFetchProducer.this.onCancellation(fetchState);
          }
        });

在NetworkFetchProducer中就实现了回调,这仍然处于子线程,那么看一看数据的回调:

private void onResponse(
      FetchState fetchState,
      InputStream responseData,
      int responseContentLength)
      throws IOException {
    final PooledByteBufferOutputStream pooledOutputStream;
    if (responseContentLength > 0) {
      pooledOutputStream = mPooledByteBufferFactory.newOutputStream(responseContentLength);
    } else {
      pooledOutputStream = mPooledByteBufferFactory.newOutputStream();
    }
    final byte[] ioArray = mByteArrayPool.get(READ_SIZE);
    try {
      int length;
      while ((length = responseData.read(ioArray)) >= 0) {
        if (length > 0) {
          pooledOutputStream.write(ioArray, 0, length);
          maybeHandleIntermediateResult(pooledOutputStream, fetchState);
          float progress = calculateProgress(pooledOutputStream.size(), responseContentLength);

          //获取数据的回调就在这里
          fetchState.getConsumer().onProgressUpdate(progress);

        }
      }
      mNetworkFetcher.onFetchCompletion(fetchState, pooledOutputStream.size());
      handleFinalResult(pooledOutputStream, fetchState);
    } finally {
      mByteArrayPool.release(ioArray);
      pooledOutputStream.close();
    }
  }

private void handleFinalResult(
      PooledByteBufferOutputStream pooledOutputStream,
      FetchState fetchState) {
    Map extraMap = getExtraMap(fetchState, pooledOutputStream.size());
    ProducerListener listener = fetchState.getListener();
    listener.onProducerFinishWithSuccess(fetchState.getId(), PRODUCER_NAME, extraMap);
    listener.onUltimateProducerReached(fetchState.getId(), PRODUCER_NAME, true);
    notifyConsumer(
        pooledOutputStream,
        Consumer.IS_LAST | fetchState.getOnNewResultStatusFlags(),
        fetchState.getResponseBytesRange(),
        fetchState.getConsumer());
  }

  private void notifyConsumer(
      PooledByteBufferOutputStream pooledOutputStream,
      @Consumer.Status int status,
      @Nullable BytesRange responseBytesRange,
      Consumer consumer) {
    CloseableReference result =
        CloseableReference.of(pooledOutputStream.toByteBuffer());
    EncodedImage encodedImage = null;
    try {
      encodedImage = new EncodedImage(result);
      encodedImage.setBytesRange(responseBytesRange);
      encodedImage.parseMetaData();
      //回调新结果
      consumer.onNewResult(encodedImage, status);
    } finally {
      EncodedImage.closeSafely(encodedImage);
      CloseableReference.closeSafely(result);
    }
  }

这里一直使用consumer.onProgressUpdate和consumer.onNewResult回调,在AbstractProducerToDataSourceAdapter类里面有具体实现:

private Consumer createConsumer() {
    return new BaseConsumer() {
      @Override
      protected void onNewResultImpl(@Nullable T newResult, @Status int status) {
        AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, status);
      }

      @Override
      protected void onFailureImpl(Throwable throwable) {
        AbstractProducerToDataSourceAdapter.this.onFailureImpl(throwable);
      }

      @Override
      protected void onCancellationImpl() {
        AbstractProducerToDataSourceAdapter.this.onCancellationImpl();
      }

      @Override
      protected void onProgressUpdateImpl(float progress) {
        AbstractProducerToDataSourceAdapter.this.setProgress(progress);
      }
    };
  }

那么在来看一下AbstractProducerToDataSourceAdapter中这些回调处理了哪些事务:

protected void onNewResultImpl(@Nullable T result, int status) {
    boolean isLast = BaseConsumer.isLast(status);
    if (super.setResult(result, isLast)) {
      if (isLast) {
        mRequestListener.onRequestSuccess(
            mSettableProducerContext.getImageRequest(),
            mSettableProducerContext.getId(),
            mSettableProducerContext.isPrefetch());
      }
    }
  }

  private void onFailureImpl(Throwable throwable) {
    if (super.setFailure(throwable)) {
      mRequestListener.onRequestFailure(
          mSettableProducerContext.getImageRequest(),
          mSettableProducerContext.getId(),
          throwable,
          mSettableProducerContext.isPrefetch());
    }
  }

由上述代码可知首先它们执行了一个super.setResult和mRequestListener.onRequestSuccess;
其中发现mResquestListener其实是由开发者自己设置的listener监听数据变化:最终由mRequestListener.onRequestSuccess接受业务执行回调,而mRequestListener的具体实现在ForwardingRequestListener类中,而我们现在具体看super.setResult中的逻辑:

protected boolean setResult(@Nullable T value, boolean isLast) {
    boolean result = setResultInternal(value, isLast);
    if (result) {
      notifyDataSubscribers();
    }
    return result;
  }

private boolean setResultInternal(@Nullable T value, boolean isLast) {
    T resultToClose = null;
    try {
      synchronized (this) {
        if (mIsClosed || mDataSourceStatus != DataSourceStatus.IN_PROGRESS) {
          resultToClose = value;
          return false;
        } else {
          if (isLast) {
            mDataSourceStatus = DataSourceStatus.SUCCESS;
            mProgress = 1;
          }
          if (mResult != value) {
            resultToClose = mResult;
            mResult = value;
          }
          return true;
        }
      }
    } finally {
      if (resultToClose != null) {
        closeResult(resultToClose);
      }
    }
  }

由上述代码知道,在数据加载完毕之后会返回true,然后执行notifyDataSubscribers,这个函数明显是通知所有订阅者状态发生改变:


  @Override
  public void subscribe(final DataSubscriber dataSubscriber, final Executor executor) {
    Preconditions.checkNotNull(dataSubscriber);
    Preconditions.checkNotNull(executor);
    boolean shouldNotify;

    synchronized(this) {
      if (mIsClosed) {
        return;
      }

      if (mDataSourceStatus == DataSourceStatus.IN_PROGRESS) {
        mSubscribers.add(Pair.create(dataSubscriber, executor));
      }

      shouldNotify = hasResult() || isFinished() || wasCancelled();
    }

    if (shouldNotify) {
      notifyDataSubscriber(dataSubscriber, executor, hasFailed(), wasCancelled());
    }
  }

private void notifyDataSubscribers() {
    final boolean isFailure = hasFailed();
    final boolean isCancellation = wasCancelled();
    for (Pair, Executor> pair : mSubscribers) {
      notifyDataSubscriber(pair.first, pair.second, isFailure, isCancellation);
    }
  }

private void notifyDataSubscriber(
      final DataSubscriber dataSubscriber,
      final Executor executor,
      final boolean isFailure,
      final boolean isCancellation) {
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            if (isFailure) {
              dataSubscriber.onFailure(AbstractDataSource.this);
            } else if (isCancellation) {
              dataSubscriber.onCancellation(AbstractDataSource.this);
            } else {
              dataSubscriber.onNewResult(AbstractDataSource.this);
            }
          }
        });
  }

protected void notifyProgressUpdate() {
    for (Pair, Executor> pair : mSubscribers) {
      final DataSubscriber subscriber = pair.first;
      Executor executor = pair.second;
      executor.execute(
          new Runnable() {
            @Override
            public void run() {
              subscriber.onProgressUpdate(AbstractDataSource.this);
            }
          });
    }
  }

这里面mSubscribers.add(Pair.create(dataSubscriber, executor));将每个subcriber与一个Executor通过一个Pair对象(相当于一个键值对)绑定在一起,那么这个executor是执行任务线程是主线程还是子线程呢:

这里需要回一下submitRequest这个函数,在getDataSource之后,它编创建了一个Subcriber并执行了Subcribe方法:

protected void submitRequest() {
    final T closeableImage = getCachedImage();
    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);
    mSettableDraweeHierarchy.setProgress(0, true);
    mIsRequestSubmitted = true;
    mHasFetchFailed = false;
    mDataSource = getDataSource();
    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 dataSubscriber =
        new BaseDataSubscriber() {
          @Override
          public void onNewResultImpl(DataSource 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 dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }
        };
    //提交订阅
    mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
  }

可以在上述代码中看到mDataSource.subscribe中传递一个mUiThreadImmediateExecutor;有此名称可见,它的任务执行线程是主线程,那么他在哪儿初始化的呢?

public PipelineDraweeControllerBuilderSupplier(
      Context context,
      ImagePipelineFactory imagePipelineFactory,
      Set boundControllerListeners,
      @Nullable DraweeConfig draweeConfig) {
    mContext = context;
    mImagePipeline = imagePipelineFactory.getImagePipeline();

    if (draweeConfig != null && draweeConfig.getPipelineDraweeControllerFactory() != null) {
      mPipelineDraweeControllerFactory = draweeConfig.getPipelineDraweeControllerFactory();
    } else {
      mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory();
    }
    mPipelineDraweeControllerFactory.init(
        context.getResources(),
        DeferredReleaser.getInstance(),
        imagePipelineFactory.getAnimatedDrawableFactory(context),
        UiThreadImmediateExecutorService.getInstance(),
        mImagePipeline.getBitmapMemoryCache(),
        draweeConfig != null
            ? draweeConfig.getCustomDrawableFactories()
            : null,
        draweeConfig != null
            ? draweeConfig.getDebugOverlayEnabledSupplier()
            : null);
    mBoundControllerListeners = boundControllerListeners;
  }

在PipelineDraweeControllerBuilderSupplier构造函数中,mPipelineDraweeControllerFactory.init第四个参数UiThreadImmediateExecutorService.getInstance()的静态实例方法作为参数传递;一起来看一下UiThreadImmediateExecutorService类的实现:

public class UiThreadImmediateExecutorService extends HandlerExecutorServiceImpl {
  private static UiThreadImmediateExecutorService sInstance = null;

  private UiThreadImmediateExecutorService() {
    super(new Handler(Looper.getMainLooper()));
  }

  public static UiThreadImmediateExecutorService getInstance() {
    if (sInstance == null) {
      sInstance = new UiThreadImmediateExecutorService();
    }
    return sInstance;
  }

  @Override
  public void execute(Runnable command) {
    if (isHandlerThread()) {
      command.run();
    } else {
      super.execute(command);
    }
  }
}

可以看到,它的构造函数这里传递了一个主线程的handler进去,到这里就大概明白了它是通过handler邮寄runnable从而达到线程切换:

public class HandlerExecutorServiceImpl extends AbstractExecutorService
    implements HandlerExecutorService {

  private final Handler mHandler;

  public HandlerExecutorServiceImpl(Handler handler) {
    mHandler = handler;
  }

  ......

  @Override
  public void execute(Runnable command) {
    mHandler.post(command);
  }
}

所以回到subcriber中,可以知道一下这段BaseDataSubscriber的具体实现是在主线程执行的:

//创建订阅者 并执行回调
    final DataSubscriber dataSubscriber =
        new BaseDataSubscriber() {
          @Override
          public void onNewResultImpl(DataSource 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 dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }
        };

最后成功回调onNewResultInternal方法完成图片内存缓存与显示并释放资源:

private void onNewResultInternal(
      String id,
      DataSource 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)) {
      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);
    } catch (Exception exception) {
      logMessageAndImage("drawable_failed @ onNewResult", image);
      releaseImage(image);
      onFailureInternal(id, dataSource, exception, isFinished);
      return;
    }
    T previousImage = mFetchedImage;
    Drawable previousDrawable = mDrawable;
    mFetchedImage = 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);
      }
    }
  }

至此,fresco加载图片结束。

最后的GenericDraweeHierarchy转换图像可以看一下

你可能感兴趣的:(Fresco图片加载源码浅析)