Fresco源码分析(二)

先看Imagepipeline:

Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要做的每个事情。
大致流程如下:

  • 检查内存缓存,如有,返回
  • 后台线程开始后续工作
  • 检查是否在未解码内存缓存中。如有,解码,变换,返回,然后缓存到内存缓存中。
  • 检查是否在磁盘缓存中,如果有,变换,返回。缓存到未解码缓存和内存缓存中。
  • 从网络或者本地加载。加载完成后,解码,变换,返回。存到各个缓存中。

总之你认为是个策略工厂

package com.facebook.imagepipeline.core;

import *

/**
 * The entry point for the image pipeline.
 */
@ThreadSafe
public class ImagePipeline {
  private static final CancellationException PREFETCH_EXCEPTION =
      new CancellationException("Prefetching is not enabled");

  private final ProducerSequenceFactory mProducerSequenceFactory;
  private final RequestListener mRequestListener;
  private final Supplier mIsPrefetchEnabledSupplier;
  private final MemoryCache mBitmapMemoryCache;
  private final MemoryCache mEncodedMemoryCache;
  private final BufferedDiskCache mMainBufferedDiskCache;
  private final BufferedDiskCache mSmallImageBufferedDiskCache;
  private final CacheKeyFactory mCacheKeyFactory;
  private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;
  private AtomicLong mIdCounter;

  public ImagePipeline(
      ProducerSequenceFactory producerSequenceFactory, // 消费和生产者模式,这个会创建网络请求片段序列
      Set requestListeners, // 这货就是最后,下载完图片,通过消费者,最后回掉用的接口
      Supplier isPrefetchEnabledSupplier,
      MemoryCache bitmapMemoryCache, // 缓存1级
      MemoryCache encodedMemoryCache, // 缓存2级
      BufferedDiskCache mainBufferedDiskCache, // Frescon 支持大图和小图区别对待,分开buff和toDisk,默认都是这个
      BufferedDiskCache smallImageBufferedDiskCache,// 小图
      CacheKeyFactory cacheKeyFactory, // 默认的key-value工厂
      ThreadHandoffProducerQueue threadHandoffProducerQueue) { // 生产者队列,用于在pause关闭资源
    mIdCounter = new AtomicLong(); // 为这个ImagePiple打一个独特内存id
    mProducerSequenceFactory = producerSequenceFactory;
    mRequestListener = new ForwardingRequestListener(requestListeners);// 这个是回掉接口包装
    mIsPrefetchEnabledSupplier = isPrefetchEnabledSupplier;
    mBitmapMemoryCache = bitmapMemoryCache;
    mEncodedMemoryCache = encodedMemoryCache;
    mMainBufferedDiskCache = mainBufferedDiskCache;
    mSmallImageBufferedDiskCache = smallImageBufferedDiskCache;
    mCacheKeyFactory = cacheKeyFactory;
    mThreadHandoffProducerQueue = threadHandoffProducerQueue;
  }

  private String generateUniqueFutureId() {
    return String.valueOf(mIdCounter.getAndIncrement());
  }

  /**
   * Returns a DataSource supplier that will on get submit the request for execution and return a
   * DataSource representing the pending results of the task.
   * 完成request,带bitmapCacheOnly这个flag策略,加载图片来源
   */
  public Supplier>> getDataSourceSupplier(
      final ImageRequest imageRequest,
      final Object callerContext,
      final boolean bitmapCacheOnly) {
    return new Supplier>>() {
      @Override
      public DataSource> get() {
        if (bitmapCacheOnly) {
          return fetchImageFromBitmapCache(imageRequest, callerContext);
        } else {
          return fetchDecodedImage(imageRequest, callerContext);
        }
      }
    };
  }

  /**
   * Returns a DataSource supplier that will on get submit the request for execution and return a
   * DataSource representing the pending results of the task.
   * 完成request,加载图片来源,磁盘或者网络
   */
  public Supplier>>
      getEncodedImageDataSourceSupplier(
          final ImageRequest imageRequest,
          final Object callerContext) {
    return new Supplier>>() {
      @Override
      public DataSource> get() {
        return fetchEncodedImage(imageRequest, callerContext);
      }
    };
  }

  /**
   * Submits a request for bitmap cache lookup.
   * 完成request,加载图片来源 图片缓存
   */
  public DataSource> fetchImageFromBitmapCache(
      ImageRequest imageRequest,
      Object callerContext) {
    try {
      Producer> producerSequence =
          mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
      return submitFetchRequest(
          producerSequence,
          imageRequest,
          ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE, //     BITMAP_MEMORY_CACHE(4); 这个等级是Bitmap caching
          callerContext);
    } catch (Exception exception) {
      return DataSources.immediateFailedDataSource(exception);
    }
  }

  /**
   * Submits a request for execution and returns a DataSource representing the pending decoded
   * image(s). 完成request,加载图片来源网络或者磁盘
   * 

The returned DataSource must be closed once the client has finished with it. */ public DataSource> fetchDecodedImage( ImageRequest imageRequest, Object callerContext) { try { Producer> producerSequence = mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest); return submitFetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, // 这个等级 Fetch (from the network or local storage) callerContext); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } /** * Submits a request for execution and returns a DataSource representing the pending encoded * image(s). * 最终要调这个Submits */ public DataSource> fetchEncodedImage( ImageRequest imageRequest, Object callerContext) { Preconditions.checkNotNull(imageRequest.getSourceUri()); try { Producer> producerSequence = mProducerSequenceFactory.getEncodedImageProducerSequence(imageRequest); // 这个很重要了,NetWork请求client在这个里面准备好 // The resize options are used to determine whether images are going to be downsampled during // decode or not. For the case where the image has to be downsampled and it's a local image it // will be kept as a FileInputStream until decoding instead of reading it in memory. Since // this method returns an encoded image, it should always be read into memory. Therefore, the // resize options are ignored to avoid treating the image as if it was to be downsampled // during decode. if (imageRequest.getResizeOptions() != null) { imageRequest = ImageRequestBuilder.fromRequest(imageRequest) .setResizeOptions(null) .build(); } return submitFetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, callerContext); // 执行生产者消费者 从这里开始了 } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } public DataSource prefetchToBitmapCache( ImageRequest imageRequest, Object callerContext) { if (!mIsPrefetchEnabledSupplier.get()) { return DataSources.immediateFailedDataSource(PREFETCH_EXCEPTION); } try { Producer producerSequence = mProducerSequenceFactory.getDecodedImagePrefetchProducerSequence(imageRequest); return submitPrefetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, callerContext, Priority.MEDIUM); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } public DataSource prefetchToDiskCache( ImageRequest imageRequest, Object callerContext, Priority priority) { if (!mIsPrefetchEnabledSupplier.get()) { return DataSources.immediateFailedDataSource(PREFETCH_EXCEPTION); } try { Producer producerSequence = mProducerSequenceFactory.getEncodedImagePrefetchProducerSequence(imageRequest); return submitPrefetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, callerContext, priority); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } ......... private DataSource> submitFetchRequest( Producer> producerSequence, ImageRequest imageRequest, ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit, Object callerContext) { try { ImageRequest.RequestLevel lowestPermittedRequestLevel = ImageRequest.RequestLevel.getMax( imageRequest.getLowestPermittedRequestLevel(), lowestPermittedRequestLevelOnSubmit); SettableProducerContext settableProducerContext = new SettableProducerContext(// 创建一个上下文对象,如同Android:Context imageRequest, generateUniqueFutureId(), mRequestListener, callerContext, lowestPermittedRequestLevel, /* isPrefetch */ false, imageRequest.getProgressiveRenderingEnabled() || !UriUtil.isNetworkUri(imageRequest.getSourceUri()), imageRequest.getPriority()); return CloseableProducerToDataSourceAdapter.create( //生产者数据源开始 producerSequence, settableProducerContext, mRequestListener); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } private DataSource submitPrefetchRequest( // 这个就是从内存拿策略和上面差不多,介绍上面那个,不同就是生产者不同 Producer producerSequence, ImageRequest imageRequest, ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit, Object callerContext, Priority priority) { try { ImageRequest.RequestLevel lowestPermittedRequestLevel = ImageRequest.RequestLevel.getMax( imageRequest.getLowestPermittedRequestLevel(), lowestPermittedRequestLevelOnSubmit); SettableProducerContext settableProducerContext = new SettableProducerContext( imageRequest, generateUniqueFutureId(), mRequestListener, callerContext, lowestPermittedRequestLevel, /* isPrefetch */ true, /* isIntermediateResultExpected */ false, priority); return ProducerToDataSourceAdapter.create( producerSequence, settableProducerContext, mRequestListener); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); } } ........ public void pause() { mThreadHandoffProducerQueue.startQueueing(); } public void resume() { mThreadHandoffProducerQueue.stopQueuing(); } public boolean isPaused() { return mThreadHandoffProducerQueue.isQueueing(); } /** * @return The CacheKeyFactory implementation used by ImagePipeline */ public CacheKeyFactory getCacheKeyFactory() { return mCacheKeyFactory; } }

在构造函数中我们看到了mRequestListener = new ForwardingRequestListener(requestListeners);这货就是提交给ImagePipleDraweeController中Listener,基本无用,默认requestListeners为null
流程:
AbstractDraweeController:sumbit() ===>PipelineDraweeController:getDataSource() ===> PipelineDraweeControllerBuilderSupplier === > ImagePipelineFactory === > ImagePipeline ===> ImagePipeline:getDataSourceSupplier() === >fetchDecodedImage() ===>ProducerSequenceFactory:getDecodedImageProducerSequence(imageRequest)处理,然后创建生产者和消费者CloseableProducerToDataSourceAdapter:create() ===>线程等级为ProducerSequenceFactory.BackGroudTask执行request
在介绍生产者之前,先把ProducerSequenceFactory这个看了

  public Producer> getDecodedImageProducerSequence(
      ImageRequest imageRequest) {
    Producer> pipelineSequence =
        getBasicDecodedImageSequence(imageRequest);// 这里开始装配
    if (imageRequest.getPostprocessor() != null) {// 判断是否有后后处理器,默认是没有
      return getPostprocessorSequence(pipelineSequence);
    } else {
      return pipelineSequence;
    }
  }

关于后处理器: 完成特殊定制,就是你在下载完成后,这个图片需要特殊要求和处理

Producer> pipelineSequence = getBasicDecodedImageSequence(imageRequest);
 private Producer> getBasicDecodedImageSequence(
      ImageRequest imageRequest) {
    Preconditions.checkNotNull(imageRequest);

    Uri uri = imageRequest.getSourceUri(); // setUrl时候构造
    Preconditions.checkNotNull(uri, "Uri is null.");
    if (UriUtil.isNetworkUri(uri)) {
      return getNetworkFetchSequence(); // 网络请求走这个
    } else if (UriUtil.isLocalFileUri(uri)) {
      if (MediaUtils.isVideo(MediaUtils.extractMime(uri.getPath()))) {
        return getLocalVideoFileFetchSequence();
      } else {
        return getLocalImageFileFetchSequence();
      }
    } else if (UriUtil.isLocalContentUri(uri)) {
      return getLocalContentUriFetchSequence();
    } else if (UriUtil.isLocalAssetUri(uri)) {
      return getLocalAssetFetchSequence();
    } else if (UriUtil.isLocalResourceUri(uri)) {
      return getLocalResourceFetchSequence();
    } else if (UriUtil.isDataUri(uri)) {
      return getDataFetchSequence();
    } else {
      String uriString = uri.toString();
      if (uriString.length() > 30) {
        uriString = uriString.substring(0, 30) + "...";
      }
      throw new RuntimeException("Unsupported uri scheme! Uri is: " + uriString);
    }
  }

其中大部分我们不关心,先找到核心请求,其它只是策略
getNetworkFetchSequence(); 不用看,就这货了。

/**
   * swallow result if prefetch -> bitmap cache get ->
   * background thread hand-off -> multiplex -> bitmap cache -> decode -> multiplex ->
   * encoded cache -> disk cache -> (webp transcode) -> network fetch.
   * 大致就是说,没有缓存你就走disk,再没有就network, multiplex是指多个request load 一起来,一样的流程,因为是有multiplex,所有同步方法
   */
  private synchronized Producer> getNetworkFetchSequence() {
    if (mNetworkFetchSequence == null) {
      mNetworkFetchSequence =
          newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
    }
    return mNetworkFetchSequence;
  }

getCommonNetworkFetchToEncodedMemorySequence() 名字已经暴露你了,什么XXX网络片段请求

 /**
   * multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch.
   */
  private synchronized Producer getCommonNetworkFetchToEncodedMemorySequence() {
    if (mCommonNetworkFetchToEncodedMemorySequence == null) {
      Producer inputProducer =
          newEncodedCacheMultiplexToTranscodeSequence(
              mProducerFactory.newNetworkFetchProducer(mNetworkFetcher));
      mCommonNetworkFetchToEncodedMemorySequence =
          ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer);

      if (mResizeAndRotateEnabledForNetwork && !mDownsampleEnabled) {
        mCommonNetworkFetchToEncodedMemorySequence =
            mProducerFactory.newResizeAndRotateProducer(
                mCommonNetworkFetchToEncodedMemorySequence);
      }
    }
    return mCommonNetworkFetchToEncodedMemorySequence;
  }

看重点,其它乱78遭,旋转改变大小又重新干一个请求,这个不看。

Fresco源码分析(二)_第1张图片
Paste_Image.png

mNetworkFetcher这货是真正底层网络代码了,默认使用HttpUrlConnectionNetworkFetcher,HttpUrlConnection的bug已经在4.3以后修复了,如果要定制okhttp,像作者一样OkHttpNetworkFetcher,需要在Frescon初始化的时候注入:com.facebook.drawee.backends.pipeline.Fresco.initialize(this, OkHttpImagePipelineConfigFactory.newBuilder(this, new okhttp3.OkHttpClient()).build());

ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer); 这货就是消费者添加图片

 public static AddImageTransformMetaDataProducer newAddImageTransformMetaDataProducer(
      Producer inputProducer) {
    return new AddImageTransformMetaDataProducer(inputProducer);
  }

/**
 * Add image transform meta data producer
 *
 * 

Extracts meta data from the results passed down from the next producer, and adds it to the * result that it returns to the consumer. */ public class AddImageTransformMetaDataProducer implements Producer { private final Producer mInputProducer; public AddImageTransformMetaDataProducer(Producer inputProducer) { mInputProducer = inputProducer; } @Override public void produceResults(Consumer consumer, ProducerContext context) { mInputProducer.produceResults(new AddImageTransformMetaDataConsumer(consumer), context); } private static class AddImageTransformMetaDataConsumer extends DelegatingConsumer< EncodedImage, EncodedImage> { private AddImageTransformMetaDataConsumer(Consumer consumer) { super(consumer); } @Override protected void onNewResultImpl(EncodedImage newResult, boolean isLast) { if (newResult == null) { getConsumer().onNewResult(null, isLast); return; } if (!EncodedImage.isMetaDataAvailable(newResult)) { newResult.parseMetaData(); } getConsumer().onNewResult(newResult, isLast); } } }

基本下载类

// 基本下载类,没有什么特点
/**
 * Network fetcher that uses the simplest Android stack.
 *
 * 

Apps requiring more sophisticated networking should implement their own * {@link NetworkFetcher}. */ public class HttpUrlConnectionNetworkFetcher extends BaseNetworkFetcher { private final ExecutorService mExecutorService; public HttpUrlConnectionNetworkFetcher() { this(Executors.newFixedThreadPool(NUM_NETWORK_THREADS)); } @VisibleForTesting HttpUrlConnectionNetworkFetcher(ExecutorService executorService) { mExecutorService = executorService; } @Override public FetchState createFetchState(Consumer consumer, ProducerContext context) { return new FetchState(consumer, context); } @Override public void fetch(final FetchState fetchState, final Callback callback) { final Future future = mExecutorService.submit( new Runnable() { @Override public void run() { fetchSync(fetchState, callback); } }); fetchState.getContext().addCallbacks( new BaseProducerContextCallbacks() { @Override public void onCancellationRequested() { if (future.cancel(false)) { callback.onCancellation(); } } }); } @VisibleForTesting void fetchSync(FetchState fetchState, Callback callback) { HttpURLConnection connection = null; try { connection = downloadFrom(fetchState.getUri(), MAX_REDIRECTS); if (connection != null) { callback.onResponse(connection.getInputStream(), -1); } } catch (IOException e) { callback.onFailure(e); } finally { 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)); } } @VisibleForTesting static HttpURLConnection openConnectionTo(Uri uri) throws IOException { URL url = new URL(uri.toString()); return (HttpURLConnection) url.openConnection(); } ......

OkHttp下载介绍

// 下面是OkHttp,使用了异步请求call.enqueue()...不知道童鞋,可以去百度下OkHttp,不难,也是建造者模式
public class OkHttpNetworkFetcher extends
    BaseNetworkFetcher {

  public static class OkHttpNetworkFetchState extends FetchState {

    public OkHttpNetworkFetchState(
        Consumer consumer,
        ProducerContext producerContext) {
      super(consumer, producerContext);
    }
  }

  private final OkHttpClient mOkHttpClient;

  private Executor mCancellationExecutor;

  /**
   * @param okHttpClient client to use
   */
  public OkHttpNetworkFetcher(OkHttpClient okHttpClient) {
    mOkHttpClient = okHttpClient;
    mCancellationExecutor = okHttpClient.dispatcher().executorService();
  }

  @Override
  public OkHttpNetworkFetchState createFetchState(
      Consumer consumer,
      ProducerContext context) {
    return new OkHttpNetworkFetchState(consumer, context);
  }

  @Override
  public void fetch(final OkHttpNetworkFetchState fetchState, final Callback callback) {
    fetchState.submitTime = SystemClock.elapsedRealtime();
    final Uri uri = fetchState.getUri();
    final Request request = new Request.Builder()
        .cacheControl(new CacheControl.Builder().noStore().build())
        .url(uri.toString())
        .get()
        .build();
    final Call call = mOkHttpClient.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;
              }

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

newBitmapCacheGetToDecodeSequence这货干缓存,前面干网络请求。

  /**
   * Same as {@code newBitmapCacheGetToBitmapCacheSequence} but with an extra DecodeProducer.
   * @param inputProducer producer providing the input to the decode
   * @return bitmap cache get to decode sequence
   */
  private Producer> newBitmapCacheGetToDecodeSequence(
      Producer inputProducer) {
    DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);
    return newBitmapCacheGetToBitmapCacheSequence(decodeProducer);
  }

DecodeProducer这货images的包装器,build模式

/**
 * Decodes images.
 *
 * 

Progressive JPEGs are decoded progressively as new data arrives. */ public class DecodeProducer implements Producer> { public static final String PRODUCER_NAME = "DecodeProducer"; // keys for extra map private static final String BITMAP_SIZE_KEY = "bitmapSize"; private static final String HAS_GOOD_QUALITY_KEY = "hasGoodQuality"; private static final String IMAGE_TYPE_KEY = "imageType"; private static final String IS_FINAL_KEY = "isFinal"; private final ByteArrayPool mByteArrayPool; private final Executor mExecutor; private final ImageDecoder mImageDecoder; private final ProgressiveJpegConfig mProgressiveJpegConfig; private final Producer mInputProducer; private final boolean mDownsampleEnabled; private final boolean mDownsampleEnabledForNetwork; ........ }

里面有执行器和byte数据池,Decoder
回归主线:
newBitmapCacheGetToBitmapCacheSequence(decodeProducer);

/**
   * Bitmap cache get -> thread hand off -> multiplex -> bitmap cache
   * @param inputProducer producer providing the input to the bitmap cache
   * @return bitmap cache get to bitmap cache sequence
   */
  private Producer> newBitmapCacheGetToBitmapCacheSequence(
      Producer> inputProducer) {
    BitmapMemoryCacheProducer bitmapMemoryCacheProducer =
        mProducerFactory.newBitmapMemoryCacheProducer(inputProducer);
    BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer =
        mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);
    ThreadHandoffProducer> threadHandoffProducer =
        mProducerFactory.newBackgroundThreadHandoffProducer(
            bitmapKeyMultiplexProducer,
            mThreadHandoffProducerQueue);
    return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);
  }

mProducerFactory.newBackgroundThreadHandoffProducer(bitmapKeyMultiplexProducer,mThreadHandoffProducerQueue);还记得前面有说ImagePipeline:mThreadHandoffProducerQueue么,这货维护请求资源,pause开打进行释放,resume反之
mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);

  public BitmapMemoryCacheGetProducer newBitmapMemoryCacheGetProducer(
      Producer> inputProducer) {
    return new BitmapMemoryCacheGetProducer(mBitmapMemoryCache, mCacheKeyFactory, inputProducer);
  }

最后塞到Cache中处理

/**
 * Bitmap memory cache producer that is read-only.
 */
public class BitmapMemoryCacheGetProducer extends BitmapMemoryCacheProducer {

  @VisibleForTesting static final String PRODUCER_NAME = "BitmapMemoryCacheGetProducer";

  public BitmapMemoryCacheGetProducer(
      MemoryCache memoryCache,
      CacheKeyFactory cacheKeyFactory,
      Producer> inputProducer) {
    super(memoryCache, cacheKeyFactory, inputProducer);
  }

  @Override
  protected Consumer> wrapConsumer(
      final Consumer> consumer,
      final CacheKey cacheKey) {
    // since this cache is read-only, we can pass our consumer directly to the next producer
    return consumer;
  }

  @Override
  protected String getProducerName() {
    return PRODUCER_NAME;
  }

消费者回掉在基类

/**
 * Memory cache producer for the bitmap memory cache.
 */
public class BitmapMemoryCacheProducer implements Producer> {

  @VisibleForTesting static final String PRODUCER_NAME = "BitmapMemoryCacheProducer";
  @VisibleForTesting static final String VALUE_FOUND = "cached_value_found";

  private final MemoryCache mMemoryCache;
  private final CacheKeyFactory mCacheKeyFactory;
  private final Producer> mInputProducer;

  public BitmapMemoryCacheProducer(
      MemoryCache memoryCache,
      CacheKeyFactory cacheKeyFactory,
      Producer> inputProducer) {
    mMemoryCache = memoryCache;
    mCacheKeyFactory = cacheKeyFactory;
    mInputProducer = inputProducer;
  }

  @Override
  public void produceResults(
      final Consumer> consumer,
      final ProducerContext producerContext) {

    final ProducerListener listener = producerContext.getListener();
    final String requestId = producerContext.getId();
    listener.onProducerStart(requestId, getProducerName());
    final ImageRequest imageRequest = producerContext.getImageRequest();
    final Object callerContext = producerContext.getCallerContext();
    final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest, callerContext);

    CloseableReference cachedReference = mMemoryCache.get(cacheKey);

    if (cachedReference != null) {
      boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality();
      if (isFinal) {
        listener.onProducerFinishWithSuccess(
            requestId,
            getProducerName(),
            listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "true") : null);
        consumer.onProgressUpdate(1f);
      }
      consumer.onNewResult(cachedReference, isFinal);
      cachedReference.close();
      if (isFinal) {
        return;
      }
    }

    if (producerContext.getLowestPermittedRequestLevel().getValue() >=
        ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {
      listener.onProducerFinishWithSuccess(
          requestId,
          getProducerName(),
          listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
      consumer.onNewResult(null, true);
      return;
    }

    Consumer> wrappedConsumer = wrapConsumer(consumer, cacheKey);
    listener.onProducerFinishWithSuccess(
        requestId,
        getProducerName(),
        listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
    mInputProducer.produceResults(wrappedConsumer, producerContext);
  }

  protected Consumer> wrapConsumer(
      final Consumer> consumer,
      final CacheKey cacheKey) {
    return new DelegatingConsumer<
        CloseableReference,
        CloseableReference>(consumer) {
      @Override
      public void onNewResultImpl(CloseableReference newResult, boolean isLast) {
        // ignore invalid intermediate results and forward the null result if last
        if (newResult == null) {
          if (isLast) {
            getConsumer().onNewResult(null, true);
          }
          return;
        }
        // stateful results cannot be cached and are just forwarded
        if (newResult.get().isStateful()) {
          getConsumer().onNewResult(newResult, isLast);
          return;
        }
        // if the intermediate result is not of a better quality than the cached result,
        // forward the already cached result and don't cache the new result.
        if (!isLast) {
          CloseableReference currentCachedResult = mMemoryCache.get(cacheKey);
          if (currentCachedResult != null) {
            try {
              QualityInfo newInfo = newResult.get().getQualityInfo();
              QualityInfo cachedInfo = currentCachedResult.get().getQualityInfo();
              if (cachedInfo.isOfFullQuality() || cachedInfo.getQuality() >= newInfo.getQuality()) {
                getConsumer().onNewResult(currentCachedResult, false);
                return;
              }
            } finally {
              CloseableReference.closeSafely(currentCachedResult);
            }
          }
        }
        // cache and forward the new result
        CloseableReference newCachedResult =
            mMemoryCache.cache(cacheKey, newResult);
        try {
          if (isLast) {
            getConsumer().onProgressUpdate(1f);
          }
          getConsumer().onNewResult(
              (newCachedResult != null) ? newCachedResult : newResult, isLast);
        } finally {
          CloseableReference.closeSafely(newCachedResult);
        }
      }
    };
  }

  protected String getProducerName() {
    return PRODUCER_NAME;
  }
}

produceResults()来自AbstractProducerToDataSourceAdapter(),往上追踪这个方法来自ImagePipleine:submitFetchRequest():CloseableProducerToDataSourceAdapter:creat()进行回掉
然后函数结尾的时候走mInputProducer.produceResults(wrappedConsumer, producerContext);
mInputProducer来自ImagePiple:fetchDecodedImage(): Producer> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
生成:ThreadHandoffProducer

/**
 * Uses ExecutorService to move further computation to different thread
 */
public class ThreadHandoffProducer implements Producer {

  @VisibleForTesting
  protected static final String PRODUCER_NAME = "BackgroundThreadHandoffProducer";

  private final Producer mInputProducer;
  private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;

  public ThreadHandoffProducer(final Producer inputProducer,
                               final  ThreadHandoffProducerQueue inputThreadHandoffProducerQueue) {
    mInputProducer = Preconditions.checkNotNull(inputProducer);
    mThreadHandoffProducerQueue = inputThreadHandoffProducerQueue;
  }

  @Override
  public void produceResults(final Consumer consumer, final ProducerContext context) {
    final ProducerListener producerListener = context.getListener();
    final String requestId = context.getId();
    final StatefulProducerRunnable statefulRunnable = new StatefulProducerRunnable(
        consumer,
        producerListener,
        PRODUCER_NAME,
        requestId) {
      @Override
      protected void onSuccess(T ignored) {
        producerListener.onProducerFinishWithSuccess(requestId, PRODUCER_NAME, null);
        mInputProducer.produceResults(consumer, context);
      }

      @Override
      protected void disposeResult(T ignored) {}

      @Override
      protected T getResult() throws Exception {
        return null;
      }
    };
    context.addCallbacks(
        new BaseProducerContextCallbacks() {
          @Override
          public void onCancellationRequested() {
            statefulRunnable.cancel();
            mThreadHandoffProducerQueue.remove(statefulRunnable);
          }
        });
    mThreadHandoffProducerQueue.addToQueueOrExecute(statefulRunnable);
  }
}

produceResults()进行队列任务

/**
 * Abstraction for computation.
 *
 * 

Computation expressed as StatefulRunnable can be cancelled, but only if it has not * started yet. * *

For better decoupling of the code computing the result and the code that handles it, 4 * separate methods are provided: getResult, onSuccess, onFailure and onCancellation. * *

This runnable can be run only once. Subsequent calls to run method won't have any effect. */ abstract public class StatefulRunnable implements Runnable { @Override public final void run() { if (!mState.compareAndSet(STATE_CREATED, STATE_STARTED)) { return; } T result; try { result = getResult(); } catch (Exception e) { mState.set(STATE_FAILED); onFailure(e); return; } mState.set(STATE_FINISHED); try { onSuccess(result); } finally { disposeResult(result); } } }

完成回掉onSuccess,上面ThreadHandoffProducer:produceResults()&StatefulProducerRunnable:onSuccess():mInputProducer.produceResults(consumer, context);而这个mInputProducer是MultiplexProducer,看下描述:

/**
 * Producer for combining multiple identical requests into a single request.
 *
 * 

Requests using the same key will be combined into a single request. This request is only * cancelled when all underlying requests are cancelled, and returns values to all underlying * consumers. If the request has already return one or more results but has not finished, then * any requests with the same key will have the most recent result returned to them immediately. * 也就是说这个类,把同样key合并成一个request,并且这个request如果被取消,那么下面所有的consumer将接收, * 还有就是如果这个request提前返回,但没有完成,那么其它的request同样key将会立即拿到返回的。 */ @ThreadSafe public abstract class MultiplexProducer implements Producer {}

然后接着继续 mInputProducer.produceResults(forwardingConsumer,multiplexProducerContext); 当前这个在MultiplexProducer的mInputProducer是BitmapMemoryCacheProducer,然后接收produceResults()进行包装

/**
 * Memory cache producer for the bitmap memory cache.
 */
public class BitmapMemoryCacheProducer implements Producer> {

 public void produceResults(
      final Consumer> consumer,
      final ProducerContext producerContext) {

    final ProducerListener listener = producerContext.getListener();
    final String requestId = producerContext.getId();
    listener.onProducerStart(requestId, getProducerName());
    final ImageRequest imageRequest = producerContext.getImageRequest();
    final Object callerContext = producerContext.getCallerContext();
    final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest, callerContext);

    CloseableReference cachedReference = mMemoryCache.get(cacheKey);

    if (cachedReference != null) {
      boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality();
      if (isFinal) {
        listener.onProducerFinishWithSuccess(
            requestId,
            getProducerName(),
            listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "true") : null);
        consumer.onProgressUpdate(1f);
      }
      consumer.onNewResult(cachedReference, isFinal);
      cachedReference.close();
      if (isFinal) {
        return;
      }
    }

    if (producerContext.getLowestPermittedRequestLevel().getValue() >=
        ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {
      listener.onProducerFinishWithSuccess(
          requestId,
          getProducerName(),
          listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
      consumer.onNewResult(null, true);
      return;
    }

    Consumer> wrappedConsumer = wrapConsumer(consumer, cacheKey);
    listener.onProducerFinishWithSuccess(
        requestId,
        getProducerName(),
        listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
    mInputProducer.produceResults(wrappedConsumer, producerContext);
  }
}

最后又走 mInputProducer.produceResults(wrappedConsumer, producerContext);这个不同了,变成了DecodeProducer去进行图片修饰,前面有说

/**
 * Decodes images.
 *
 * 

Progressive JPEGs are decoded progressively as new data arrives. */ public class DecodeProducer implements Producer> { @Override public void produceResults( final Consumer> consumer, final ProducerContext producerContext) { final ImageRequest imageRequest = producerContext.getImageRequest(); ProgressiveDecoder progressiveDecoder; if (!UriUtil.isNetworkUri(imageRequest.getSourceUri())) { progressiveDecoder = new LocalImagesProgressiveDecoder(consumer, producerContext); } else { ProgressiveJpegParser jpegParser = new ProgressiveJpegParser(mByteArrayPool); progressiveDecoder = new NetworkImagesProgressiveDecoder( consumer, producerContext, jpegParser, mProgressiveJpegConfig); } mInputProducer.produceResults(progressiveDecoder, producerContext); } }

mInputProducer这货不看了,这个是ResizeAndRotateProducer,旋转有关的,NetworkImagesProgressiveDecoder里面有jobSclude

/**
 * Decodes images.
 *
 * 

Progressive JPEGs are decoded progressively as new data arrives. */ public class DecodeProducer implements Producer> { public ProgressiveDecoder( final Consumer> consumer, final ProducerContext producerContext) { super(consumer); mProducerContext = producerContext; mProducerListener = producerContext.getListener(); mImageDecodeOptions = producerContext.getImageRequest().getImageDecodeOptions(); mIsFinished = false; JobRunnable job = new JobRunnable() { @Override public void run(EncodedImage encodedImage, boolean isLast) { if (encodedImage != null) { // 这里开始接收到finsh if (mDownsampleEnabled) { ImageRequest request = producerContext.getImageRequest(); if (mDownsampleEnabledForNetwork || !UriUtil.isNetworkUri(request.getSourceUri())) { encodedImage.setSampleSize(DownsampleUtil.determineSampleSize( request, encodedImage)); } } doDecode(encodedImage, isLast); } } }; mJobScheduler = new JobScheduler(mExecutor, job, mImageDecodeOptions.minDecodeIntervalMs); mProducerContext.addCallbacks( new BaseProducerContextCallbacks() { @Override public void onIsIntermediateResultExpectedChanged() { if (mProducerContext.isIntermediateResultExpected()) { mJobScheduler.scheduleJob(); } } }); } }

然后job做完,会拿到回掉,走doDecode(encodedImage, isLast);

/**
 * Decodes images.
 *
 * 

Progressive JPEGs are decoded progressively as new data arrives. */ public class DecodeProducer implements Producer> { /** Performs the decode synchronously. */ private void doDecode(EncodedImage encodedImage, boolean isLast) { if (isFinished() || !EncodedImage.isValid(encodedImage)) { // 校验 return; } try { long queueTime = mJobScheduler.getQueuedTime();// 校验 int length = isLast ?// 校验 encodedImage.getSize() : getIntermediateImageEndOffset(encodedImage); QualityInfo quality = isLast ? ImmutableQualityInfo.FULL_QUALITY : getQualityInfo();// 校验 // 这个还是ForwardingRequestListener,基本无用,因为里面包装的requstListener是空 mProducerListener.onProducerStart(mProducerContext.getId(), PRODUCER_NAME); CloseableImage image = null; try { image = mImageDecoder.decodeImage(encodedImage, length, quality, mImageDecodeOptions); // 按图片类型加载 } catch (Exception e) { Map extraMap = getExtraMap(image, queueTime, quality, isLast); mProducerListener. onProducerFinishWithFailure(mProducerContext.getId(), PRODUCER_NAME, e, extraMap); handleError(e); return; } Map extraMap = getExtraMap(image, queueTime, quality, isLast); mProducerListener. onProducerFinishWithSuccess(mProducerContext.getId(), PRODUCER_NAME, extraMap); handleResult(image, isLast); } finally { EncodedImage.closeSafely(encodedImage); } } }

mImageDecoder.decodeImage()将会调用ImageDecoder,这个类有点流弊,有谁知道'pinned'这个技术么,希望告诉我详细,关于内存的,以前bitmap保存在Ashmen后来sdk变高以后,bitmap挂载在java heap去维护了

Fresco 的 Image Pipeline 负责图片的获取和管理。

  • 图片可以来自远程服务器,本地文件,或者Content Provider,本地资源。压缩后的文件缓存在本地存储中,Bitmap数据缓存在内存中。
  • 在5.0系统之后,Image Pipeline 使用`pinned purgeables*将Bitmap数据存在native 内存中。这要求图片不使用时,要显示地释放内存。
  • SimpleDraweeView 自动处理了这个释放过程,所以没有特殊情况,尽量使用SimpleDraweeView,在特殊的场合,如果有需要,也可以直接控制Image Pipeline。
Pinned purgeables behave as specified in {@link android.graphics.BitmapFactory.Options#inPurgeable}
public class BitmapFactory {

     public static class Options {
        /**
         * @deprecated As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this is
         * ignored.
         *
         * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, if this
         * is set to true, then the resulting bitmap will allocate its
         * pixels such that they can be purged if the system needs to reclaim
         * memory. In that instance, when the pixels need to be accessed again
         * (e.g. the bitmap is drawn, getPixels() is called), they will be
         * automatically re-decoded.
         *
         * 

For the re-decode to happen, the bitmap must have access to the * encoded data, either by sharing a reference to the input * or by making a copy of it. This distinction is controlled by * inInputShareable. If this is true, then the bitmap may keep a shallow * reference to the input. If this is false, then the bitmap will * explicitly make a copy of the input data, and keep that. Even if * sharing is allowed, the implementation may still decide to make a * deep copy of the input data.

* *

While inPurgeable can help avoid big Dalvik heap allocations (from * API level 11 onward), it sacrifices performance predictability since any * image that the view system tries to draw may incur a decode delay which * can lead to dropped frames. Therefore, most apps should avoid using * inPurgeable to allow for a fast and fluid UI. To minimize Dalvik heap * allocations use the {@link #inBitmap} flag instead.

* *

Note: This flag is ignored when used * with {@link #decodeResource(Resources, int, * android.graphics.BitmapFactory.Options)} or {@link #decodeFile(String, * android.graphics.BitmapFactory.Options)}.

*/ @Deprecated public boolean inPurgeable; } }

基本是说,inPurgeable,造成bitmap被系统回收通过pixels,因此,在fast和fluid ui(快速流畅)避免使用,GC时间长,为了使用小heap资源,sdk给inBitmap标志代替

关于Bitmap的回收机制

系统的Bitmap内存管理机制随着Android系统的演进可以分为三个阶段,关于这部分可以参考官网文章Managing Bitmap Memory。

  • 2.3.3及以下:Bitmap的像素数据存储在native内存中,但依旧会计算在一个进程的内存上限之中。
  • 3.0~4.4:Bitmap的像素数据存储在Java堆内存中,解码Bitmap时可以通过Options#inBitmap复用不再使用的Bitmap,从而减少系统gc。但要求被复用的Bitmap和新Bitmap的像素数据一样大。
  • 5.0及以上:对于复用Bitmap的限制不再严格要求一样大,只要别复用的Bitmap的像素数据不小于新Bitmap即可。
/**
 * Decodes images.
 *
 * 

ImageDecoder implements image type recognition and passes decode requests to * specialized methods implemented by subclasses. * * On dalvik, it produces 'pinned' purgeable bitmaps. * *

Pinned purgeables behave as specified in * {@link android.graphics.BitmapFactory.Options#inPurgeable} with one modification. The bitmap is * 'pinned' so is never purged. * *

For API 21 and higher, this class produces standard Bitmaps, as purgeability is not supported * on the most recent versions of Android. */ public class ImageDecoder { /** * Decodes image. * * @param encodedImage input image (encoded bytes plus meta data) * @param length if image type supports decoding incomplete image then determines where * the image data should be cut for decoding. * @param qualityInfo quality information for the image * @param options options that cange decode behavior */ public CloseableImage decodeImage( final EncodedImage encodedImage, final int length, final QualityInfo qualityInfo, final ImageDecodeOptions options) { ImageFormat imageFormat = encodedImage.getImageFormat(); if (imageFormat == null || imageFormat == ImageFormat.UNKNOWN) { imageFormat = ImageFormatChecker.getImageFormat_WrapIOException( encodedImage.getInputStream()); } switch (imageFormat) { case UNKNOWN: throw new IllegalArgumentException("unknown image format"); case JPEG: return decodeJpeg(encodedImage, length, qualityInfo); case GIF: return decodeGif(encodedImage, options); case WEBP_ANIMATED: return decodeAnimatedWebp(encodedImage, options); default: return decodeStaticImage(encodedImage); } } }

最后这个bitmap的Cahe会传到Multiplexer&ForwardingConsumer:consumer然后找到对应订阅Pair, ProducerContext> 然后就回到了最开始AbstractDraweeController:submitRequest()的datasource订阅者了,完成成功,失败,数据持续更新一系列主线程刷新。
好了,差不多介绍完主要的,细节我会持续补充的。

你可能感兴趣的:(Fresco源码分析(二))