从源码角度深入理解Glide(中)

glide_logo.png

上两一篇文章从源码角度深入理解Glide(上)中,我们了解了Glide框架中的一些用法,并且分析了Glide的with方法和load方法,由于简书限制字数篇幅原因into方法留到本篇文章分析,废话不多说,接下来马上开始分析。

into方法

  • 通过上一小节的分析,经过load方法之后获取的对象是RequestBuilder,并且我们将load方法的参数赋值给了RequestBuilder对象的model参数,接下来就到了Glide最核心的方法,也就是RequestBuilder对象的into方法
获取DrawableImageViewTarget
/** RequestBuilder 类的into方法*/
@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);
    RequestOptions requestOptions = this.requestOptions;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      // Clone in this method so that if we use this RequestBuilder to load into a View and then
      // into a different target, we don't retain the transformation applied based on the previous
      // View's scale type.
      switch (view.getScaleType()) {
        case CENTER_CROP:
          requestOptions = requestOptions.clone().optionalCenterCrop();
          break;
        case CENTER_INSIDE:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case FIT_CENTER:
        case FIT_START:
        case FIT_END:
          requestOptions = requestOptions.clone().optionalFitCenter();
          break;
        case FIT_XY:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case CENTER:
        case MATRIX:
        default:
          // Do nothing.
      }
    }

    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);
  }
  • RequestBuilder 对象的into方法中首先获取传递进来的ImageView的ScaleType,让Glide加载出来的ImageView保持一样的ScaleType变化,然后我们看到最后一句话,该方法返回了RequestBuilder 对象的另一个into方法,先看glideContext.buildImageViewTarget()做了什么操作
/** GlideContext 类的 buildImageViewTarget方法*/
  @NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  public class ImageViewTargetFactory {
  @NonNull
  @SuppressWarnings("unchecked")
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
      //省略代码
      .....
    }
  }
}
  • 通过以上源码,之前我们看RequestBuilder源码中as方法传入的是Drawable.class,所以以上的buildImageViewTarget方法最终返回的是DrawableImageViewTarget对象,接着我们继续看第一步into方法返回into方法中做了什么操作
构建Request
/** RequestBuilder 类的into方法返回的into方法*/
 private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    options = options.autoClone();
    Request request = buildRequest(target, targetListener, options);
    //省略部分代码
    ......
    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);
    return target;
  }
  • 通过以上源码,我们应该先明白Request类是一个接口,他抽象了Glide加载图片请求(Request类源码这里就不贴了),它是一个非常重要的类,这里我们先看看buildRequest(target, targetListener, options)方法是如何创建Request对象的
 private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      RequestOptions requestOptions) {
    return buildRequestRecursive(
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions);
  }
private Request buildRequestRecursive(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
   //省略部分代码 error Request build
    ..... 
    Request mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions);

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }
    //省略部分代码 error Request build
    ..... 
  }
  
  private Request buildThumbnailRequestRecursive(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
    if (thumbnailBuilder != null) {
      //省略部分代码 缩略图操作
    .....
    } else {
      // Base case: no thumbnail.
      return obtainRequest(
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight);
    }
  }

  private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      RequestOptions requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory());
  }
  • 通过上面的源码,我们可以看到buildRequest方法调用了buildRequestRecursive方法,在buildRequestRecursive方法中大部分代码都在处理缩略图(thumbnail),我们主流程中没有设置缩略图,这里就不进行展开分析,接着buildRequestRecursive方法又调用了obtainRequest方法,obtainRequest方法传递了非常多参数,比如有我们熟悉的RequestOptions,设置图片尺寸的 overrideWidth, overrideHeight,还有第一步into方法中的target对象,也就是DrawableImageViewTarget对象,model也就是我们load传入的图片地址,也就说明不管load方法还是apply方法传入的参数最终都给到了这里传入SingleRequest.obtain方法,我们继续看看SingleRequest类
public final class SingleRequest<R> implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
//省略部分代码
......
/**SingleRequest类的 obtain方法*/
 public static <R> SingleRequest<R> obtain(
      Context context,
      GlideContext glideContext,
      Object model,
      Class<R> transcodeClass,
      RequestOptions requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory) {
    @SuppressWarnings("unchecked") SingleRequest<R> request =
        (SingleRequest<R>) POOL.acquire();
    if (request == null) {
      request = new SingleRequest<>();
    }
    request.init(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory);
    return request;
  }
  //省略部分代码
  ......
}  
  • 通过SingleRequest对象的obtain方法,我们可以看到request = new SingleRequest<>();也就是最终我们构建的Request是SingleRequest对象,并在init方法中将上一步obtainRequest方法传递进来的各种参数进行赋值。
Request执行
  • 构建完成Request对象,接下来继续看刚刚的into方法下面的操作
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target
  • 首先RequestManager对象清除target,此时不懂你是否还记得RequestManager,该对象是第一步with方法之后得到的,接着是将我们上一步得到的SingleRequest对象设置给target,接着又执行了RequestManager.track方法,继续跟进该方法看看
/** RequestManager 类的track方法*/
void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
/** RequestTracker 类的runRequest方法*/  
private final List<Request> pendingRequests = new ArrayList<>();
 public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      pendingRequests.add(request);
    }
  }  
  • 通过上面的源码,RequestManager对象的track方法中执行了RequestTracker 类的runRequest方法,该方法中简单判断当前Glide是否在暂停状态,不是暂停状态则执行Request的begin方法,否则将这个Request加入到请求队列List<Request>pendingRequests中.
后备回调符、加载占位符和错误占位符加载
  • 接下来我们看看Request的begin方法到底干了啥,要找到begin方法实现,根据前面分析,我们则应该去看SingleRequest对象的begin方法
/** SingleRequest 类的begin方法*/  
@Override
  public void begin() {
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
      int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }

    if (status == Status.RUNNING) {
      throw new IllegalArgumentException("Cannot restart a running request");
    }
    if (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }
    status = Status.WAITING_FOR_SIZE;
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
      onSizeReady(overrideWidth, overrideHeight);
    } else {
      target.getSize(this);
    }
    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      target.onLoadStarted(getPlaceholderDrawable());
    }
    if (IS_VERBOSE_LOGGABLE) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
  }
  
  private void onLoadFailed(GlideException e, int maxLogLevel) {
      //省略部分代码
      .......
      if (!anyListenerHandledUpdatingTarget) {
        setErrorPlaceholder();
      }
     //省略部分代码
     ....... 
  }
  • 通过以上begin方法源码,如果model为空,也就是我们load传入的图片地址为空,则会调用onLoadFailed方法,而onLoadFailed方法又调用了setErrorPlaceholder方法,接着看看该方法中做了什么操作
/** SingleRequest 类的setErrorPlaceholder方法*/ 
private void setErrorPlaceholder() {
    if (!canNotifyStatusChanged()) {
      return;
    }
    Drawable error = null;
    if (model == null) {
      error = getFallbackDrawable();
    }
    // Either the model isn't null, or there was no fallback drawable set.
    if (error == null) {
      error = getErrorDrawable();
    }
    // The model isn't null, no fallback drawable was set or no error drawable was set.
    if (error == null) {
      error = getPlaceholderDrawable();
    }
    target.onLoadFailed(error);
  }
  
  private Drawable getErrorDrawable() {
    if (errorDrawable == null) {
      errorDrawable = requestOptions.getErrorPlaceholder();
      if (errorDrawable == null && requestOptions.getErrorId() > 0) {
        errorDrawable = loadDrawable(requestOptions.getErrorId());
      }
    }
    return errorDrawable;
  }
  • 通过以上源码,如果我们传入图片地址为空,则首先查看是否有后备回调符设置,然后是错误占位符,最后是加载占位符,最终调用target.onLoadFailed方法,也就是ImageViewTarget的onLoadFailed方法
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>implements Transition.ViewAdapter {
  //省略部分代码
  .......
  public void setDrawable(Drawable drawable) {
    view.setImageDrawable(drawable);
  }
  
  @Override
  public void onLoadStarted(@Nullable Drawable placeholder) {
    super.onLoadStarted(placeholder);
    setResourceInternal(null);
    setDrawable(placeholder);
  }

  @Override
  public void onLoadFailed(@Nullable Drawable errorDrawable) {
    super.onLoadFailed(errorDrawable);
    setResourceInternal(null);
    setDrawable(errorDrawable);
  }
  //省略部分代码
  .......
}
  • 通过以上源码,我想你应该已经明白了后备回调符、错误占位符加载,这里还有一个疑问,加载占位符呢?我们回到之前SingleRequest对象的begin方法,相信你会马上看到在加载状态为RUNNING的时候调用了target.onLoadStarted,也实现了加载中的占位符,到这里我们已经分析完了后备回调符、加载占位符和错误占位符加载底层实现逻辑。
加载图片网络请求
  • 前面分析完各种占位符实现,我们再次回到SingleRequest对象的begin方法,我们可以注意到onSizeReady()和target.getSize()这两句就是加载图片的入口,如果我们在使用glide的时候设置图片加载的大小尺寸,则会调用target.getSize()
/** ViewTarget 类的etSize方法*/ 
void getSize(@NonNull SizeReadyCallback cb) {
      int currentWidth = getTargetWidth();
      int currentHeight = getTargetHeight();
      if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
        cb.onSizeReady(currentWidth, currentHeight);
        return;
      }
      //省略部分代码
      ......
    }
  • 通过以上源码,target.getSize()会根据ImageView的宽高来得出图片的加载宽高,最终target.getSize()还是会调用onSizeReady()方法,所以我们就直接来看看SingleRequest对象onSizeReady()方法中做了什么操作。
/** SingleRequest 类的onSizeReady方法*/
@Override
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    if (IS_VERBOSE_LOGGABLE) {
      logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
    if (status != Status.WAITING_FOR_SIZE) {
      return;
    }
    status = Status.RUNNING;

    float sizeMultiplier = requestOptions.getSizeMultiplier();
    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

    if (IS_VERBOSE_LOGGABLE) {
      logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }
    loadStatus = engine.load(
        glideContext,
        model,
        requestOptions.getSignature(),
        this.width,
        this.height,
        requestOptions.getResourceClass(),
        transcodeClass,
        priority,
        requestOptions.getDiskCacheStrategy(),
        requestOptions.getTransformations(),
        requestOptions.isTransformationRequired(),
        requestOptions.isScaleOnlyOrNoTransform(),
        requestOptions.getOptions(),
        requestOptions.isMemoryCacheable(),
        requestOptions.getUseUnlimitedSourceGeneratorsPool(),
        requestOptions.getUseAnimationPool(),
        requestOptions.getOnlyRetrieveFromCache(),
        this);

    // This is a hack that's only useful for testing right now where loads complete synchronously
    // even though under any executor running on any thread but the main thread, the load would
    // have completed asynchronously.
    if (status != Status.RUNNING) {
      loadStatus = null;
    }
    if (IS_VERBOSE_LOGGABLE) {
      logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
  }
  • 在onSizeReady方法中,主要调用了engine.load()方法并返回加载状态,engine.load方法继续接收我们之前传入的各种参数,其中也有我们model对象,也就是之前load方法传入的图片地址。首先我们需要了解engine是什么,顾名思义,engine的英文意思是发动机,而在Glide框架中他就是负责启动图片加载的发动机,主要负责启动加载,我们在前面with方法获取glide对象中得到了engine对象(这里就不贴源码了),我们接着看engine.load()方法进行什么操作
/** Engine 类的load方法*/
public <R> LoadStatus load(GlideContext glideContext, Object model,Key signature,int width,int height,Class<?> resourceClass,Class<R> transcodeClass, Priority priority,DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations,boolean isTransformationRequired,boolean isScaleOnlyOrNoTransform,Options options,boolean isMemoryCacheable,boolean useUnlimitedSourceExecutorPool,boolean useAnimationPool,boolean onlyRetrieveFromCache,ResourceCallback cb) {
    Util.assertMainThread();
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);

    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return null;
    }
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return null;
    }
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb);
    engineJob.start(decodeJob);

    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }
/**  DecodeJob 类的继承关系*/  
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable   
  • 通过以上源码,Engine对象的load方前面一段代码都是在处理缓存问题,这里先不进行展开,继续走我们加载图片的主线,往下看我们看到构建了一个EngineJob对象,还构建了一个DecodeJob对象,构建DecodeJob对象又继续接收我们之前传入的各种参数,由DecodeJob对象的继承关系我们可以知道它是Runnable对象,接着我们看到engineJob的start()方法,它直接传入了DecodeJob对象
/** EngineJob 类的start方法*/
public void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }
/** GlideExecutor 类的newSourceExecutor方法*/  
public static GlideExecutor newSourceExecutor(
      int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) {
    return new GlideExecutor(
        new ThreadPoolExecutor(
            threadCount /* corePoolSize */,
            threadCount /* maximumPoolSize */,
            0 /* keepAliveTime */,
            TimeUnit.MILLISECONDS,
            new PriorityBlockingQueue<Runnable>(),
            new DefaultThreadFactory(name, uncaughtThrowableStrategy, false)));
  }  
  • 通过以上源码,EngineJob对象的start方法首先还是判断缓存,最终获取的GlideExecutor就是一个线程池执行器(Executor),GlideExecutor中有各种方法获得缓存线程池,还有资源线程池(SourceExecutor),以上源码贴出资源线程池。实际上EngineJob对象的start方法就是用来在线程池中启动DecodeJob这个Runnable对象,也就是说EngineJob的主要作用是开启线程来加载图片,接着我们来看看DecodeJob对象的run方法。
/** DecodeJob 类的run方法*/
public void run() {
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (Throwable t) {
      //省略部分代码
      .......
    } finally {
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }
/** DecodeJob 类的runWrapped方法*/  
private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
/** DecodeJob 类的getNextStage方法*/   
private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }
 /** DecodeJob 类的getNextGenerator方法*/   
private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      case RESOURCE_CACHE:
        return new ResourceCacheGenerator(decodeHelper, this);
      case DATA_CACHE:
        return new DataCacheGenerator(decodeHelper, this);
      case SOURCE:
        return new SourceGenerator(decodeHelper, this);
      case FINISHED:
        return null;
      default:
        throw new IllegalStateException("Unrecognized stage: " + stage);
    }
 /** DecodeJob 类的runGenerators方法*/       
 private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
   //省略部分代码
      ....... 
  }    
  • 上面我们再次贴出了一堆代码,我们来好好梳理一下逻辑,DecodeJob对象的run方法中逻辑很简单,就是调用了自身的runWrapped方法,runWrapped方法中首先判断Stage枚举,前面在创建DecodeJob对象时候设置初始状态为Stage.INITIALIZE,然后接着调用getNextStage方法,这里我们还是继续跳过缓存,所以getNextStage方法最终返回的是Stage.SOURCE状态,接着在getNextGenerator()方法中我们获取就是SourceGenerator对象,也就是run方法中的第一句话DataFetcher<?> localFetcher = currentFetcher中localFetcher就是我们刚刚获得的SourceGenerator对象,接着继续执行runGenerators()方法,在该方法的while循环判断条件执行了currentGenerator.startNext()方法,也就是SourceGenerator对象的startNext()方法
/** SourceGenerator 类的startNext()方法*/ 
@Override
  public boolean startNext() {
    //省略部分代码,跳过缓存部分判断
    ........
    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }
/** DecodeHelper 类的getLoadData() 方法*/
List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        LoadData<?> current =
            modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }
/** HttpGlideUrlLoader 类的buildLoadData 方法*/ 
 @Override
  public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
      @NonNull Options options) {
    // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
    // spent parsing urls.
    GlideUrl url = model;
    if (modelCache != null) {
      url = modelCache.get(model, 0, 0);
      if (url == null) {
        modelCache.put(model, 0, 0, model);
        url = model;
      }
    }
    int timeout = options.get(TIMEOUT);
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  } 
  • 通过上面源码,我们接着看到loadData=helper.getLoadData().get(loadDataListIndex++)这一句代码,helper就是DecodeHelper对象,在我们前面创建DecodeJob对象的时候已经把它创建,之前我们在load步骤中传入的model是图片url地址,所以经过DecodeHelper 类的getLoadData() 方法(更细的代码这里就不进行展开了),最终获取的ModelLoader<Object, ?> modelLoader对象则为HttpGlideUrlLoader对象,也就是laodData对象,所以modelLoader.buildLoadData创建则在HttpGlideUrlLoader对象的buildLoadData中实现,上方贴出的该方法源码中把我们model赋值给GlideUrl对象,也就是将其作为URL地址来进行处理,则经过modelLoader.buildLoadData获取的loadData.fetcher则对应HttpUrlFetcher对象,所以loadData.fetcher.loadData调用的就是HttpUrlFetcher对象loadData方法,
/**HttpUrlFetcher类的loadData方法 **/
@Override
  public void loadData(@NonNull Priority priority,
      @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      callback.onDataReady(result);
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
    } finally {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
/**HttpUrlFetcher类的loadDataWithRedirects方法 **/  
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
      Map<String, String> headers) throws IOException {
    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
      // Comparing the URLs using .equals performs additional network I/O and is generally broken.
      // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
      try {
        if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
          throw new HttpException("In re-direct loop");

        }
      } catch (URISyntaxException e) {
        // Do nothing, this is best effort.
      }
    }

    urlConnection = connectionFactory.build(url);
    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
    urlConnection.setConnectTimeout(timeout);
    urlConnection.setReadTimeout(timeout);
    urlConnection.setUseCaches(false);
    urlConnection.setDoInput(true);

    // Stop the urlConnection instance of HttpUrlConnection from following redirects so that
    // redirects will be handled by recursive calls to this method, loadDataWithRedirects.
    urlConnection.setInstanceFollowRedirects(false);

    // Connect explicitly to avoid errors in decoders if connection fails.
    urlConnection.connect();
    // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
    stream = urlConnection.getInputStream();
    if (isCancelled) {
      return null;
    }
    final int statusCode = urlConnection.getResponseCode();
    if (isHttpOk(statusCode)) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      String redirectUrlString = urlConnection.getHeaderField("Location");
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url");
      }
      URL redirectUrl = new URL(url, redirectUrlString);
      // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
      // to disconnecting the url connection below. See #2352.
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }  
  • 通过以上源码,HttpUrlFetcher对象的loadData方法首先调用自身loadDataWithRedirects方法,接着我们看到该方法源码,这里使用了HttpURLConnection来执行了网络请求,看到这里内心还是有点开心的,前面看了这么多源码,终于看到Glide的网络请求了,开心之后还没完呢,还得接着往下看,执行完网络请求成功,loadDataWithRedirects方法中网络请求成功调用getStreamForSuccessfulRequest返回了一个InputStream流(记住这个InputStream,很关键),然后执行了一个callback回调,而这个回调对象就是我们之前在SourceGenerator对象中调用loadData方法传入SourceGenerator对象本身,所以callback.onDataReady()调用的就是SourceGenerator对象的onDataReady方法
/**SourceGenerator类的onDataReady方法 **/  
  @Override
  public void onDataReady(Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      // We might be being called back on someone else's thread. Before doing anything, we should
      // reschedule to get back onto Glide's thread.
      cb.reschedule();
    } else {
      cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
          loadData.fetcher.getDataSource(), originalKey);
    }
  }
  • 通过以上源码,不走缓存的情况下则调用cb.onDataFetcherReady,这个cb也就是前面我们new SourceGenerator对象传入的 DecodeJob对象,也就是调用DecodeJob对象onDataFetcherReady方法
/**DecodeJob类的onDataFetcherReady方法 **/ 
 @Override
  public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
      DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
  • 通过以上源码,onDataFetcherReady方法中将之前网络请求得到的流赋值给当前的DecodeJob对象的currentData,其他数据都赋值给对应字段,最终调用的是decodeFromRetrievedData方法
加载图片(解码,转码)
/**DecodeJob类的decodeFromRetrievedData方法 **/ 
private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Retrieved data", startFetchTime,
          "data: " + currentData
              + ", cache key: " + currentSourceKey
              + ", fetcher: " + currentFetcher);
    }
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }
/**DecodeJob类的decodeFromData方法 **/   
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
      DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } finally {
      fetcher.cleanup();
    }
  }
/**DecodeJob类的decodeFromFetcher方法 **/  
 private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
      throws GlideException {
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
    return runLoadPath(data, dataSource, path);
  }
  • 通过以上源码,decodeFromRetrievedData方法调用了decodeFromFetcher方法,在该方法中首先通过decodeHelper.getLoadPath获取LoadPath对象,LoadPath对象其实是根据我们传入的处理数据来返回特定的数据解码转码处理器,我们跟进decodeHelper.getLoadPath看看
/** DecodeHelper类的getLoadPath方法*/
<Data> LoadPath<Data, ?, Transcode> getLoadPath(Class<Data> dataClass) {
    return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);
  }
/** Registry类的getLoadPath方法*/
 @Nullable
  public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> getLoadPath(
      @NonNull Class<Data> dataClass, @NonNull Class<TResource> resourceClass,
      @NonNull Class<Transcode> transcodeClass) {
    //省略部分代码
    .......
     List<DecodePath<Data, TResource, Transcode>> decodePaths =
          getDecodePaths(dataClass, resourceClass, transcodeClass);
      if (decodePaths.isEmpty()) {
        result = null;
      } else {
        result =
            new LoadPath<>(
                dataClass, resourceClass, transcodeClass, decodePaths, throwableListPool);
      }
      loadPathCache.put(dataClass, resourceClass, transcodeClass, result);
    }
    return result;
  } 
/** Registry类的getDecodePaths方法*/ 
@NonNull
  private <Data, TResource, Transcode> List<DecodePath<Data, TResource, Transcode>> getDecodePaths(
      @NonNull Class<Data> dataClass, @NonNull Class<TResource> resourceClass,
      @NonNull Class<Transcode> transcodeClass) {
      //省略部分代码,去除干扰

        List<ResourceDecoder<Data, TResource>> decoders =
            decoderRegistry.getDecoders(dataClass, registeredResourceClass);
        ResourceTranscoder<TResource, Transcode> transcoder =
            transcoderRegistry.get(registeredResourceClass, registeredTranscodeClass);
        @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
        DecodePath<Data, TResource, Transcode> path =
            new DecodePath<>(dataClass, registeredResourceClass, registeredTranscodeClass,
                decoders, transcoder, throwableListPool);
        decodePaths.add(path);
    }
    return decodePaths;
  }
 /** Registry类的getDecoders方法*/  
 public synchronized <T, R> List<ResourceDecoder<T, R>> getDecoders(@NonNull Class<T> dataClass,
      @NonNull Class<R> resourceClass) {
    List<ResourceDecoder<T, R>> result = new ArrayList<>();
    for (String bucket : bucketPriorityList) {
      List<Entry<?, ?>> entries = decoders.get(bucket);
      if (entries == null) {
        continue;
      }
      for (Entry<?, ?> entry : entries) {
        if (entry.handles(dataClass, resourceClass)) {
          result.add((ResourceDecoder<T, R>) entry.decoder);
        }
      }
    }
    // TODO: cache result list.

    return result;
  } 
  • 通过以上源码,我们接着前面跟进DecodeHelper.getLoadPath方法,它调用了Registry对象的getLoadPath方法,Registry对象的getLoadPath方法又调用了自身的getDecodePaths方法,现在我前面提到过得我们网络请求获取的是InputStream流,所以上面源码getDecodePaths方法中Data泛型就是InputStream,在根据getDecoders方法遍历得到解码器ResourceDecoder能处理InputStream流的有StreamBitmapDecoder和StreamGifDecoder,StreamGifDecoder处理的是Gif,我们这里处理图片就之能是StreamBitmapDecoder,它将InputStream流解码成bitmap,然后能将bitmap转换成Drawable的转码器ResourceTranscoder对象则是BitmapDrawableTranscoder,最后getDecodePaths将我们刚刚分析得到的解码器和转码器传递给了新建的DecodePath对象,DecodePath对象就是用来帮助我们进行解码和转码的。
  • 接着我们继续上一步的decodeFromFetcher方法,该方法返回的runLoadPath最终调用了上面获得的DecodePath对象的decode方法
/**DecodePath类的decode方法**/
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
      @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    return transcoder.transcode(transformed, options);
  }
/**DecodePath类的decodeResource方法**/
@NonNull
  private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
      int height, @NonNull Options options) throws GlideException {
    List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
    try {
      return decodeResourceWithList(rewinder, width, height, options, exceptions);
    } finally {
      listPool.release(exceptions);
    }
  }
/**DecodePath类的decodeResourceWithList方法**/
  @NonNull
  private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
      int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
    Resource<ResourceType> result = null;
    //省略部分代码
    ........
      ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
      try {
        DataType data = rewinder.rewindAndGet();
        if (decoder.handles(data, options)) {
          data = rewinder.rewindAndGet();
          result = decoder.decode(data, width, height, options);
        }
    //省略部分代码
    ........
    return result;
  }  
  • 通过以上源码,DecodePath对象的decode方法调用了decodeResource方法,decodeResource又调用了decodeResourceWithList方法,经过前面分析,decodeResourceWithList方法中获得的decoder就是前面提到的解码器StreamBitmapDecoder对象,所以我们接着看StreamBitmapDecoder的decode方法
/**StreamBitmapDecoder类的decode方法**/
@Override
  public Resource<Bitmap> decode(@NonNull InputStream source, int width, int height,
      @NonNull Options options)
      throws IOException {

    // Use to fix the mark limit to avoid allocating buffers that fit entire images.
    final RecyclableBufferedInputStream bufferedStream;
    final boolean ownsBufferedStream;
    if (source instanceof RecyclableBufferedInputStream) {
      bufferedStream = (RecyclableBufferedInputStream) source;
      ownsBufferedStream = false;
    } else {
      bufferedStream = new RecyclableBufferedInputStream(source, byteArrayPool);
      ownsBufferedStream = true;
    }

    ExceptionCatchingInputStream exceptionStream =
        ExceptionCatchingInputStream.obtain(bufferedStream);
    MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream);
    UntrustedCallbacks callbacks = new UntrustedCallbacks(bufferedStream, exceptionStream);
    try {
      return downsampler.decode(invalidatingStream, width, height, options, callbacks);
    } finally {
      exceptionStream.release();
      if (ownsBufferedStream) {
        bufferedStream.release();
      }
    }
  }
  • 通过以上源码,StreamBitmapDecoder的decode方法中只是对InputStream进行包装(装饰模式),可以让Glide进行更多操作,最终调用了downsampler.decode,这个downsampler对象则是Downsampler对象(英文注释:Downsamples, decodes, and rotates images according to their exif orientation.),英文注释大致意思是对图像exif格式进行采样、解码和旋转。而我们这里调用了它的decode方法,也就是对我们前面包装的流进行解码
/**Downsampler类的decode方法**/
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
      Options options, DecodeCallbacks callbacks) throws IOException {
    //省略部分代码
    try {
      Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
          downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
          requestedHeight, fixBitmapToRequestedDimensions, callbacks);
      return BitmapResource.obtain(result, bitmapPool);
    } finally {
      releaseOptions(bitmapFactoryOptions);
      byteArrayPool.put(bytesForOptions);
    }
  }
/**Downsampler类的decodeFromWrappedStreams方法**/  
private Bitmap decodeFromWrappedStreams(InputStream is,
      BitmapFactory.Options options, DownsampleStrategy downsampleStrategy,
      DecodeFormat decodeFormat, boolean isHardwareConfigAllowed, int requestedWidth,
      int requestedHeight, boolean fixBitmapToRequestedDimensions,
      DecodeCallbacks callbacks) throws IOException {
    //省略部分代码
    .........
    Bitmap downsampled = decodeStream(is, options, callbacks, bitmapPool);
    callbacks.onDecodeComplete(bitmapPool, downsampled);
    //省略部分代码
    .........
    Bitmap rotated = null;
    if (downsampled != null) {
      //缩放效正处理
      downsampled.setDensity(displayMetrics.densityDpi);
      rotated = TransformationUtils.rotateImageExif(bitmapPool, downsampled, orientation);
      if (!downsampled.equals(rotated)) {
        bitmapPool.put(downsampled);
      }
    }
    return rotated;
  }
/**Downsampler类的decodeStream方法**/  
private static Bitmap decodeStream(InputStream is, BitmapFactory.Options options,
      DecodeCallbacks callbacks, BitmapPool bitmapPool) throws IOException {
    if (options.inJustDecodeBounds) {
      is.mark(MARK_POSITION);
    } else {
      callbacks.onObtainBounds();
    }
    int sourceWidth = options.outWidth;
    int sourceHeight = options.outHeight;
    String outMimeType = options.outMimeType;
    final Bitmap result;
    TransformationUtils.getBitmapDrawableLock().lock();
    try {
      result = BitmapFactory.decodeStream(is, null, options);
    } catch (IllegalArgumentException e) {
      //省略部分代码
    .........
    return result;
  }  
  • 通过以上源码,Downsampler对象的decode方法首先调用了decodeFromWrappedStreams方法,在decodeFromWrappedStreams方法中又调用了decodeStream方法,在该方法中调用用了BitmapFactory.decodeStream,到这里我们终于看到了Glide将InputStream流解析成了bitmap,而最终Downsampler对象的decode方法返回的Resource对象就是BitmapResource对象
  • 经过前面的分析,Glide已经将InputStream解码完成,这时我们还得再次回到DecodePath对象的decode方法,解码完成还需转码,这里再次贴一下ecodePath对象的decode方法,前面已经分析了转码器为BitmapDrawableTranscoder对象,所以我们继续看BitmapDrawableTranscoder对象transcode做了什么操作
/**DecodePath类的decode方法**/  
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
      @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    return transcoder.transcode(transformed, options);
  }
/**BitmapDrawableTranscoder类的transcode方法**/  
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
      @NonNull Options options) {
    return LazyBitmapDrawableResource.obtain(resources, toTranscode);
  } 
/**LazyBitmapDrawableResource类的obtain方法**/  
@Nullable
  public static Resource<BitmapDrawable> obtain(
      @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
    if (bitmapResource == null) {
      return null;
    }
    return new LazyBitmapDrawableResource(resources, bitmapResource);
  }
  • 通过以上源码,BitmapDrawableTranscoder对象transcode方法最终返回了LazyBitmapDrawableResource对象,也就是将我们解码拿到的BitmapResource对象转换成了LazyBitmapDrawableResource对象

到此,Glide整个图片解码转码已近完成,接着我们再回到DecodeJob对象的decodeFromRetrievedData方法

图片显示
/**DecodeJob类的decodeFromRetrievedData方法**/
private void decodeFromRetrievedData() {
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }
/**DecodeJob类的notifyEncodeAndRelease方法**/  
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    //省略部分代码
    .....
    Resource<R> result = resource;
    //省略部分代码
    .....
    notifyComplete(result, dataSource);
    stage = Stage.ENCODE;
    //省略部分代码
    .....
  }
/**DecodeJob类的notifyComplete方法**/    
 private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    callback.onResourceReady(resource, dataSource);
  }  
  • 通过以上源码,DecodeJob对象的decodeFromRetrievedData方法调用notifyEncodeAndRelease方法,将我们上一步获取的LazyBitmapDrawableResource传入notifyComplete方法中,在notifyComplete调用了callback.onResourceReady,而这个callback对象就是EngineJob对象(它实现了DecodeJob.Callback接口),也许到这里你已经忘了EngineJob对象是什么,前面我们开启线程执行加载的start方法就在EngineJob对象中,所以我们去看看EngineJob对象的onResourceReady方法
private static final Handler MAIN_THREAD_HANDLER =
      new Handler(Looper.getMainLooper(), new MainThreadCallback());
/**EngineJob类的onResourceReady方法**/
@Override
  public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    this.resource = resource;
    this.dataSource = dataSource;
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
  }
/**EngineJob类的handleMessage方法**/
 @Override
    public boolean handleMessage(Message message) {
      EngineJob<?> job = (EngineJob<?>) message.obj;
      switch (message.what) {
        case MSG_COMPLETE:
          job.handleResultOnMainThread();
          break;
        case MSG_EXCEPTION:
          job.handleExceptionOnMainThread();
          break;
        case MSG_CANCELLED:
          job.handleCancelledOnMainThread();
          break;
        default:
          throw new IllegalStateException("Unrecognized message: " + message.what);
      }
      return true;
    } 
/**EngineJob类的handleResultOnMainThread方法**/    
 @Synthetic
  void handleResultOnMainThread() {
    //省略部分代码
    ......
    engineResource = engineResourceFactory.build(resource, isCacheable);
    hasResource = true;
   //省略部分代码
    ......
    for (int i = 0, size = cbs.size(); i < size; i++) {
      ResourceCallback cb = cbs.get(i);
      if (!isInIgnoredCallbacks(cb)) {
        engineResource.acquire();
        cb.onResourceReady(engineResource, dataSource);
      }
    }
    //省略部分代码
    ......
  }
/**EngineJob类的addCallback方法**/ 
private final List<ResourceCallback> cbs = new ArrayList<>(2);
void addCallback(ResourceCallback cb) {
    Util.assertMainThread();
    stateVerifier.throwIfRecycled();
    if (hasResource) {
      cb.onResourceReady(engineResource, dataSource);
    } else if (hasLoadFailed) {
      cb.onLoadFailed(exception);
    } else {
      cbs.add(cb);
    }
  }  
  • 通过以上源码,前面我们在Engine类的Load方法中已经将SingleRequest这个对象通过EngineJob对象的addCallback方法加入到了cbs这个List当中,EngineJob对象的onResourceReady方法中将我们加载好的图片对象通过Hanlder将数据又传递到了主线程(主线程更新UI),也就是handleResultOnMainThread方法中根据我们刚刚的分析通过cb.onResourceReady将数据回调通知,cb对象就是SingleRequest对象,我们接着看SingleRequest对象的onResourceReady回调方法
/**SingleRequest类的onResourceReady回调方法**/
@SuppressWarnings("unchecked")
@Override
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
    //省略部分代码
    .......
    Object received = resource.get();
    //省略部分代码
    .......
    onResourceReady((Resource<R>) resource, (R) received, dataSource);
  }
/**SingleRequest类的onResourceReady方法**/  
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    //省略部分代码
    .......
    status = Status.COMPLETE;
    this.resource = resource;
    //省略部分代码
    .......
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation =
            animationFactory.build(dataSource, isFirstResource);
        target.onResourceReady(result, animation);
      }
    } 
    //省略部分代码
    .......
  }

通过以上源码,这时候我们已经可以看到长征胜利的曙光了,SingleRequest对象的onResourceReady回调方法中调用了resource.get(),而这个resource就是前面我们经过解码、转码获取的LazyBitmapDrawableResource对象,然后又调用了SingleRequest对象的onResourceReady私有方法,在该方法中又调用了target.onResourceReady方法,在我们最开始进入into方法的时候我们已经分析过创建的target对象就是DrawableImageViewTarget对象,它继承了抽象类ImageViewTarget,所以我们看看抽象类ImageViewTarget的onResourceReady方法

/** LazyBitmapDrawableResource类的get()方法**/
@NonNull
  @Override
  public BitmapDrawable get() {
    return new BitmapDrawable(resources, bitmapResource.get());
  }

/** ImageViewTarget类的onResourceReady方法**/
 @Override
  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }
/** ImageViewTarget类的setResourceInternal方法**/  
 private void setResourceInternal(@Nullable Z resource) {
    // Order matters here. Set the resource first to make sure that the Drawable has a valid and
    // non-null Callback before starting it.
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }
  protected abstract void setResource(@Nullable Z resource);
  • 通过以上源码,LazyBitmapDrawableResource对象的get()方法获取了BitmapDrawable(实际就是Drawable对象),ImageViewTarget对象的onResourceReady方法通过前面分析被调用,然后该方法再调用了ImageViewTarget对象setResourceInternal方法,setResourceInternal方法最终setResource方法,setResource在ImageViewTarget对象是抽象方法,它在DrawableImageViewTarget对象中实现,最后我们看看DrawableImageViewTarget对象setResource方法
 @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }

到此,我们的万里长征终于结束了,Glide的简单加载图片流程已经分析完了。

最后说点

  • 最后我还是想要把那句简单的代码给贴出来
Glide.with(Context).load(IMAGE_URL).into(mImageView);
  • 就是这样一句简单的代码,它背后所走的逻辑却让人头皮发麻,此时我只想说一句话“read the fuck source code”。前面我们只是分析了Glide简单的加载图片流程,它的缓存使用,回调等各种功能原理还没分析到,这只能等到下篇文章了。文章中如果有错误,请大家给我提出来,大家一起学习进步,如果觉得我的文章给予你帮助,也请给我一个喜欢和关注,同时也欢迎访问我的个人博客

  • 对本文感兴趣的朋友请继续阅读从源码角度深入理解Glide(下)

  • 参考链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268