Glide v4 源码浅析(4)-into(下)

513 阅读11分钟

简述

接上部分《Glide v4 源码浅析(3)-into(上)》,继续分析获取到源数据后,对数据进行解码转换处理,并最终设置到ImageView上。

源码分析

decode和transcode

进入decodeFromData方法:

private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
    DataSource dataSource) throws GlideException {
  try {
    if (data == null) {
      return null;
    }
    long startTime = LogTime.getLogTime();
    // 又调用decodeFromFetcher方法解码数据。
    Resource<R> result = decodeFromFetcher(data, dataSource);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Decoded result " + result, startTime);
    }
    return result;
  } finally {
    // 释放fetcher中占用的资源。
    fetcher.cleanup();
  }
}

接着看decodeFromFetcher方法:

private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
    throws GlideException {
  // getLoadPath方法在前面执行过,已经存有dataClass对应的LoadPath,这里可以快速获取。
  LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
  return runLoadPath(data, dataSource, path);
}

继续看runLoadPath方法:

private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
    LoadPath<Data, ResourceType, R> path) throws GlideException {
  Options options = getOptionsWithHardwareConfig(dataSource);
  // 根据Data类型从DataRewinderRegistry检索对应的DataRewinder。这里的Data类型为MappedByteBuffer,
  // 因此rewinder实例为ByteBufferRewinder。
  DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
  try {
    // ResourceType in DecodeCallback below is required for compilation to work with gradle.
    return path.load(
        rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
  } finally {
    rewinder.cleanup();
  }
}

LoadPath.load中又调用了loadWithExceptionList方法:

private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
    @NonNull Options options,
    int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
    List<Throwable> exceptions) throws GlideException {
  Resource<Transcode> result = null;
  //noinspection ForLoopReplaceableByForEach to improve perf
  for (int i = 0, size = decodePaths.size(); i < size; i++) {
    // 依次取出DecodePath进行解码尝试。
    DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
    try {
      result = path.decode(rewinder, width, height, options, decodeCallback);
    } catch (GlideException e) {
      exceptions.add(e);
    }
    // 若成功解码数据,就结束循环,返回结果。
    if (result != null) {
      break;
    }
  }

  if (result == null) {
    throw new GlideException(failureMessage, new ArrayList<>(exceptions));
  }

  return result;
}

进入DecodePath的decode方法:

public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
    @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
  // 通过之前收集好的ResourceDecoder尝试解码,获得解码后资源。
  Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
  // 回调给DecodeJob的onResourceDecoded方法,会根据宽高、缩放、裁剪类型返回转换后的资源。
  Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
  // 返回使用ResourceTranscoder转码后的资源。
  return transcoder.transcode(transformed, options);
}

该方法中分三步对资源进行处理:

  1. 使用ResourceDecoder进行解码;
  2. 使用Transformation进行转换;
  3. 使用ResourceTranscoder进行转码。

一. decodeResource 先看第一步,decodeResource中又调用了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;
  //noinspection ForLoopReplaceableByForEach to improve perf
  for (int i = 0, size = decoders.size(); i < size; i++) {
    // 依次尝试ResourceDecoder。
    ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
    try {
      // 本例中rewinder为ByteBufferRewinder,返回position置0后的MappedByteBuffer。
      DataType data = rewinder.rewindAndGet();
      // 初步匹配类型和选项。
      if (decoder.handles(data, options)) {
        data = rewinder.rewindAndGet();
        // 本例中可用的decoder为ByteBufferBitmapDecoder,直接看它的decode方法。
        result = decoder.decode(data, width, height, options);
      }
      // Some decoders throw unexpectedly. If they do, we shouldn't fail the entire load path, but
      // instead log and continue. See #2406 for an example.
    } catch (IOException | RuntimeException | OutOfMemoryError e) {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Failed to decode data for " + decoder, e);
      }
      exceptions.add(e);
    }

    if (result != null) {
      break;
    }
  }

  if (result == null) {
    throw new GlideException(failureMessage, new ArrayList<>(exceptions));
  }
  // 返回解码成功的资源。
  return result;
}

进入ByteBufferBitmapDecoder的decode方法:

@Override
public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
    @NonNull Options options)
    throws IOException {
  // toStream方法返回ByteBufferStream(继承自InputStream),包装了ByteBuffer。
  InputStream is = ByteBufferUtil.toStream(source);
  // 从传入的is中解码出Bitmap。
  return downsampler.decode(is, width, height, options);
}

Downsampler的decode方法最终调用了:

public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
    Options options, DecodeCallbacks callbacks) throws IOException {
  // ByteBufferStream重写了markSupported方法返回true。
  Preconditions.checkArgument(is.markSupported(), "You must provide an InputStream that supports"
      + " mark()");

  // 分配解码时的临时空间。
  byte[] bytesForOptions = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
  BitmapFactory.Options bitmapFactoryOptions = getDefaultOptions();
  bitmapFactoryOptions.inTempStorage = bytesForOptions;

  // 获取解码格式。
  DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
  // 获取采样策略。
  DownsampleStrategy downsampleStrategy = options.get(DownsampleStrategy.OPTION);
  // bitmap尺寸是否适配目标尺寸。
  boolean fixBitmapToRequestedDimensions = options.get(FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS);
  // 是否启用硬件位图。
  boolean isHardwareConfigAllowed =
    options.get(ALLOW_HARDWARE_CONFIG) != null && options.get(ALLOW_HARDWARE_CONFIG);

  try {
    // 解码得到Bitmap。
    Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
        downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
        requestedHeight, fixBitmapToRequestedDimensions, callbacks);
    // 对Bitmap包装并返回。
    return BitmapResource.obtain(result, bitmapPool);
  } finally {
    releaseOptions(bitmapFactoryOptions);
    byteArrayPool.put(bytesForOptions);
  }
}

接着看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 {
  long startTime = LogTime.getLogTime();

  // 通过设置options.inJustDecodeBounds为true,再调用BitmapFactory.decodeStream,获得原始数据的尺寸。
  int[] sourceDimensions = getDimensions(is, options, callbacks, bitmapPool);
  int sourceWidth = sourceDimensions[0];
  int sourceHeight = sourceDimensions[1];
  String sourceMimeType = options.outMimeType;

  // If we failed to obtain the image dimensions, we may end up with an incorrectly sized Bitmap,
  // so we want to use a mutable Bitmap type. One way this can happen is if the image header is so
  // large (10mb+) that our attempt to use inJustDecodeBounds fails and we're forced to decode the
  // full size image.
  if (sourceWidth == -1 || sourceHeight == -1) {
    isHardwareConfigAllowed = false;
  }

  // 从图片文件header中获取exif信息,通过exif读取方向信息。
  int orientation = ImageHeaderParserUtils.getOrientation(parsers, is, byteArrayPool);
  // 获取图像旋转角度。
  int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation);
  // 若exif方法信息指明有旋转/翻转,则为true。
  boolean isExifOrientationRequired = TransformationUtils.isExifOrientationRequired(orientation);

  // 确定目标尺寸。
  int targetWidth = requestedWidth == Target.SIZE_ORIGINAL ? sourceWidth : requestedWidth;
  int targetHeight = requestedHeight == Target.SIZE_ORIGINAL ? sourceHeight : requestedHeight;

  // 获取图片格式。
  ImageType imageType = ImageHeaderParserUtils.getType(parsers, is, byteArrayPool);

  // 根据图片旋转角度和ImageView的mScaleType缩放策略(outside、inside、fit等)和原始尺寸与目标尺寸比计算inSampleSize。
  // 再根据图片格式计算inTargetDensity和inDensity,并根据inTargetDensity和inDensity的值设置inScaled。
  calculateScaling(
      imageType,
      is,
      callbacks,
      bitmapPool,
      downsampleStrategy,
      degreesToRotate,
      sourceWidth,
      sourceHeight,
      targetWidth,
      targetHeight,
      options);
  // 判断是否支持硬件位图,设置inPreferredConfig和inMutable。
  calculateConfig(
      is,
      decodeFormat,
      isHardwareConfigAllowed,
      isExifOrientationRequired,
      options,
      targetWidth,
      targetHeight);

  boolean isKitKatOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  // Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding.
  // 判断是否能够使用inBitmap(内存块复用)。低于4.4版本需要找到相同大小的bitmap才能复用,4.4+的允许大于尺寸的bitmap。
  if ((options.inSampleSize == 1 || isKitKatOrGreater) && shouldUsePool(imageType)) {
    int expectedWidth;
    int expectedHeight;
    if (sourceWidth >= 0 && sourceHeight >= 0
        && fixBitmapToRequestedDimensions && isKitKatOrGreater) {
      expectedWidth = targetWidth;
      expectedHeight = targetHeight;
    } else {
      float densityMultiplier = isScaling(options)
          ? (float) options.inTargetDensity / options.inDensity : 1f;
      int sampleSize = options.inSampleSize;
      int downsampledWidth = (int) Math.ceil(sourceWidth / (float) sampleSize);
      int downsampledHeight = (int) Math.ceil(sourceHeight / (float) sampleSize);
      expectedWidth = Math.round(downsampledWidth * densityMultiplier);
      expectedHeight = Math.round(downsampledHeight * densityMultiplier);

      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Calculated target [" + expectedWidth + "x" + expectedHeight + "] for source"
            + " [" + sourceWidth + "x" + sourceHeight + "]"
            + ", sampleSize: " + sampleSize
            + ", targetDensity: " + options.inTargetDensity
            + ", density: " + options.inDensity
            + ", density multiplier: " + densityMultiplier);
      }
    }
    // If this isn't an image, or BitmapFactory was unable to parse the size, width and height
    // will be -1 here.
    if (expectedWidth > 0 && expectedHeight > 0) {
      // 设置inBitmap,其中还会判断inPreferredConfig,不能为HARDWARE。
      setInBitmap(options, bitmapPool, expectedWidth, expectedHeight);
    }
  }
  // 设置完Options后,通过BitmapFactory.decodeStream获得Bitmap。
  Bitmap downsampled = decodeStream(is, options, callbacks, bitmapPool);
  // 该回调中默认什么都不执行。
  callbacks.onDecodeComplete(bitmapPool, downsampled);

  if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logDecode(sourceWidth, sourceHeight, sourceMimeType, options, downsampled,
        requestedWidth, requestedHeight, startTime);
  }

  Bitmap rotated = null;
  if (downsampled != null) {
    // If we scaled, the Bitmap density will be our inTargetDensity. Here we correct it back to
    // the expected density dpi.
    downsampled.setDensity(displayMetrics.densityDpi);

    // 设置Matrix,通过Canvas.drawBitmap对Bitmap进行旋转/翻转。
    rotated = TransformationUtils.rotateImageExif(bitmapPool, downsampled, orientation);
    if (!downsampled.equals(rotated)) {
      bitmapPool.put(downsampled);
    }
  }

  return rotated;
}

在Downsampler中经过缩放、设置采样率、旋转/翻转等操作,最终将InputStream转换成Bitmap返回。

二. transform 回到DecodePath的decode方法中,接下来将通过回调,将Bitmap传到DecodeJob的onResourceDecoded中,进行transform处理:

@Synthetic
@NonNull
<Z> Resource<Z> onResourceDecoded(DataSource dataSource,
    @NonNull Resource<Z> decoded) {
  @SuppressWarnings("unchecked")
  // 此时decoded为包装了Bitmap的BitmapResource对象,返回的是Bitmap类型。
  Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
  Transformation<Z> appliedTransformation = null;
  Resource<Z> transformed = decoded;
  // 此时dataSource为REMOTE。
  if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
    // 获取Bitmap.class对应的Transformation。
    // ImageView的缩放类型默认为FIT_CENTER,此时获取相对应的FitCenter实例。
    appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
    // 这里根据FIT_CENTER缩放策略计算宽高,然后从bitmapPool中取一块复用的Bitmap内存块,接着设置Matrix,最后通过canvas.drawBitmap绘制。
    transformed = appliedTransformation.transform(glideContext, decoded, width, height);
  }
  // TODO: Make this the responsibility of the Transformation.
  // 判断是否有生成新的Bitmap,如果根据缩放策略计算的宽高是一致的,则不会生成新的。
  if (!decoded.equals(transformed)) {
    // 将变换前的Bitmap存入bitmapPool中,留待下次复用内存块。
    decoded.recycle();
  }

  final EncodeStrategy encodeStrategy;
  final ResourceEncoder<Z> encoder;
  if (decodeHelper.isResourceEncoderAvailable(transformed)) {
  	// 获取在ResourceEncoderRegistry在注册的Bitmap.class对应的BitmapEncoder。
    encoder = decodeHelper.getResultEncoder(transformed);
    // 获取到对应的EncodeStrategy.TRANSFORMED。
    encodeStrategy = encoder.getEncodeStrategy(options);
  } else {
    encoder = null;
    encodeStrategy = EncodeStrategy.NONE;
  }

  Resource<Z> result = transformed;
  boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
  // 这里判断资源是否可缓存,此时判断为false,跳过。
  if (diskCacheStrategy.isResourceCacheable(isFromAlternateCacheKey, dataSource,
      encodeStrategy)) {
    if (encoder == null) {
      throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
    }
    // 生成新key。
    final Key key;
    switch (encodeStrategy) {
      case SOURCE:
        key = new DataCacheKey(currentSourceKey, signature);
        break;
      case TRANSFORMED:
        key =
            new ResourceCacheKey(
                decodeHelper.getArrayPool(),
                currentSourceKey,
                signature,
                width,
                height,
                appliedTransformation,
                resourceSubClass,
                options);
        break;
      default:
        throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
    }

    LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
    // 用于在将转码后的资源返回给外部调用者后,再对资源进行编码保存。
    deferredEncodeManager.init(key, encoder, lockedResult);
    result = lockedResult;
  }
  // 这里不执行上面if方法体,返回转换后的资源。
  return result;
}

该方法中,再通过Transformation对资源进行了依次转换。

三. transcode 回到DecodePath的decode方法中,资源经过transform后,传给ResourceTranscoder进行transcode,进入BitmapDrawableTranscoder:

@Nullable
@Override
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
    @NonNull Options options) {
  return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}

使用LazyBitmapDrawableResource对象再进行一层包装。

通知资源就绪

decode方法中经过解码转换,最终创建包装了对Bitmap层层包装后的LazyBitmapDrawableResource实例,一直返回到DecodeJob的decodeFromRetrievedData方法中。

private void decodeFromRetrievedData() {
  ···
  // 此时resource为LazyBitmapDrawableResource实例。
  if (resource != null) {
    notifyEncodeAndRelease(resource, currentDataSource);
  } else {
    runGenerators();
  }
}

看notifyEncodeAndRelease方法:

private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
  if (resource instanceof Initializable) {
    ((Initializable) resource).initialize();
  }

  Resource<R> result = resource;
  LockedResource<R> lockedResource = null;
  // 这里为false。
  if (deferredEncodeManager.hasResourceToEncode()) {
    lockedResource = LockedResource.obtain(resource);
    result = lockedResource;
  }

  // 通知资源就绪。
  notifyComplete(result, dataSource);

  stage = Stage.ENCODE;
  try {
    // 这里为false,不执行编码保存磁盘操作。
    if (deferredEncodeManager.hasResourceToEncode()) {
      deferredEncodeManager.encode(diskCacheProvider, options);
    }
  } finally {
    if (lockedResource != null) {
      lockedResource.unlock();
    }
  }
  // Call onEncodeComplete outside the finally block so that it's not called if the encode process
  // throws.
  // 最后释放此DecodeJob的资源,解除成员变量的引用。
  onEncodeComplete();
}

notifyComplete方法中回调了EngineJob的onResourceReady方法:

@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
  // 此时resource为LazyBitmapDrawableResource。
  this.resource = resource;
  // 此时dataSource为REMOTE。
  this.dataSource = dataSource;
  // 通过主线程handler发送到主线程中处理。
  MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}

看MAIN_THREAD_HANDLER注册的Handler.Callback中的handleMessage方法:

@Override
publicboolean handleMessage(Message message) {
  EngineJob<?> job = (EngineJob<?>) message.obj;
  // 此时的what为MSG_COMPLETE。
  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;
}

看handleResultOnMainThread方法:

@Synthetic
void handleResultOnMainThread() {
  stateVerifier.throwIfRecycled();
  if (isCancelled) {
    // 判断若取消了本次加载,将Bitmap放入bitmapPool中。
    resource.recycle();
    // 释放此EngineJob的资源。
    release(false /*isRemovedFromQueue*/);
    return;
  } else if (cbs.isEmpty()) {
    throw new IllegalStateException("Received a resource without any callbacks to notify");
  } else if (hasResource) {
    throw new IllegalStateException("Already have resource");
  }
  // 重新EngineResource,包装加载到的资源。
  engineResource = engineResourceFactory.build(resource, isCacheable);
  // hasResource标识置为true。
  hasResource = true;

  // Hold on to resource for duration of request so we don't recycle it in the middle of
  // notifying if it synchronously released by one of the callbacks.
  // 增加资源引用计数。
  engineResource.acquire();
  // 回调到Engine中:
  // 1.给engineResource添加资源释放监听器;
  // 2.若可缓存,加入活动资源缓存集合。
  // 3.从当前请求任务集合移出。
  listener.onEngineJobComplete(this, key, engineResource);

  //noinspection ForLoopReplaceableByForEach to improve perf
  for (int i = 0, size = cbs.size(); i < size; i++) {
    // 遍历保存的回调,即依次通知重复请求的外部调用者。
    ResourceCallback cb = cbs.get(i);
    // 排除已取消的调用者回调。
    if (!isInIgnoredCallbacks(cb)) {
      // 增加活动资源引用计数。
      engineResource.acquire();
      // 回调通知资源就绪。
      cb.onResourceReady(engineResource, dataSource);
    }
  }
  // Our request is complete, so we can release the resource.
  // 引用计数剪一。
  // 若上面仍在监听的回调为空,则表明没有在活动的调用者引用此资源。
  // 将通知Engine将该资源从活动资源集合中移除,然后将该资源加入内存缓存集合或者释放该资源。
  engineResource.release();

  // 释放EngineJob的资源。
  release(false /*isRemovedFromQueue*/);
}

这里的ResourceCallback为SingleRequest实例,看它的onResourceReady方法:

@Override
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
  stateVerifier.throwIfRecycled();
  loadStatus = null;
  if (resource == null) {
    GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
        + "object of " + transcodeClass + " inside, but instead got null.");
    onLoadFailed(exception);
    return;
  }

  // 取出包装的BitmapDrawable。
  Object received = resource.get();
  // 检查返回的资源对象类型是否匹配。
  if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
    releaseResource(resource);
    GlideException exception = new GlideException("Expected to receive an object of "
        + transcodeClass + " but instead" + " got "
        + (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
        + "Resource{" + resource + "}."
        + (received != null ? "" : " " + "To indicate failure return a null Resource "
        + "object, rather than a Resource object containing null data."));
    onLoadFailed(exception);
    return;
  }

  // requestCoordinator默认为null,canSetResource返回true。
  if (!canSetResource()) {
    releaseResource(resource);
    // We can't put the status to complete before asking canSetResource().
    status = Status.COMPLETE;
    return;
  }

  onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
  // We must call isFirstReadyResource before setting status.
  // requestCoordinator默认为null,因此isFirstReadyResource返回true。
  boolean isFirstResource = isFirstReadyResource();
  status = Status.COMPLETE;
  this.resource = resource;

  if (glideContext.getLogLevel() <= Log.DEBUG) {
    Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
        + dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
        + LogTime.getElapsedMillis(startTime) + " ms");
  }

  isCallingCallbacks = true;
  try {
    boolean anyListenerHandledUpdatingTarget = false;
    // requestListeners默认为空。
    if (requestListeners != null) {
      for (RequestListener<R> listener : requestListeners) {
        anyListenerHandledUpdatingTarget |=
            listener.onResourceReady(result, model, target, dataSource, isFirstResource);
      }
    }
    // targetListener默认为空,因此anyListenerHandledUpdatingTarget为false。
    anyListenerHandledUpdatingTarget |=
        targetListener != null
            && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);

	// 若上面listener有一个返回true,就不再执行target的回调。
    if (!anyListenerHandledUpdatingTarget) {
      // 创建Transition,用于显示动画效果,默认为NoTransition,不做任何动效。
      Transition<? super R> animation =
          animationFactory.build(dataSource, isFirstResource);
      // 回调target资源就绪。
      target.onResourceReady(result, animation);
    }
  } finally {
    isCallingCallbacks = false;
  }

  // 通知加载请求成功。若有requestCoordinator,将递归调用下一个请求。
  notifyLoadSuccess();
}

这里的target为在调用RequestBuilder的into方法时创建的DrawableImageViewTarget,这里回调它父类ImageViewTarget的onResourceReady:

@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
  // transition默认为空,不做动效,直接展示。
  if (transition == null || !transition.transition(resource, this)) {
    setResourceInternal(resource);
  } else {
    maybeUpdateAnimatable(resource);
  }
}

接着看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);
  // 判断资源对象是否实现了Animatable,若支持动画播放,则会播放。
  maybeUpdateAnimatable(resource);
}

setResource为抽象方法,在DrawableImageViewTarget中实现:

@Override
protected void setResource(@Nullable Drawable resource) {
  // 调用了ImageView的setImageDrawable方法,将BitmapDrawable设置上去展示。
  view.setImageDrawable(resource);
}

可以看到最终将BitmapDrawable传给了ImageView展示。

总结

以上就是Glide的最简单的使用例子的执行流程。