Glide解析(二)

load时序图:

RequestBuilder : 这是一个通用请求构建类,可以处理通用资源类型的设置选项
和启动负载。

load 函数加载相对于比较简单。我们看下具体代码实现

public class RequestManager implements LifecycleListener,
  ModelTypes<RequestBuilder<Drawable>> {
  
.....
 
 public RequestBuilder<Drawable> load(@Nullable String string) {
  //这里调用 Drawable 图片加载请求器为其加载
  return asDrawable().load(string);
}
 public RequestBuilder<Drawable> asDrawable() {
  return as(Drawable.class);
}
 @NonNull
 @CheckResult
 @Override
 public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
 @NonNull
 @CheckResult
 @Override
 public RequestBuilder<Drawable> load(@Nullable File file) {
  return asDrawable().load(file);
}
 
 public <ResourceType> RequestBuilder<ResourceType> as(
   @NonNull Class<ResourceType> resourceClass) {
  return new RequestBuilder<>(glide, this, resourceClass,
context);
}    
}

看看load详情:

public class RequestBuilder<TranscodeType> extends
BaseRequestOptions<RequestBuilder<TranscodeType>>
  implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
   
 public RequestBuilder<TranscodeType> load(@Nullable String
string) {
  return loadGeneric(string);
}
 // 描述加载的数据源-这里可以看做是我们刚刚传递进来的 http://xxxx.png
 @Nullable private Object model;
 // 描述这个请求是否已经添加了加载的数据源
 private boolean isModelSet;
 private RequestBuilder<TranscodeType> loadGeneric(@Nullable
Object model) {
  this.model = model;
  isModelSet = true;
  return this;
}
}

到这里 RequestBuilder 就构建好了, RequestBuilder构建出来后,都是
为了后面的into

into时序图:

@NonNull
 public ViewTarget<ImageView, TranscodeType> into(@NonNull
ImageView view) {
  Util.assertMainThread();
  Preconditions.checkNotNull(view);
  // 根据 ImageView 布局中的 scaleType 来重构 requestOptions
  BaseRequestOptions<?> requestOptions = this;
  if (!requestOptions.isTransformationSet()
    && requestOptions.isTransformationAllowed()
    && view.getScaleType() != null) {
   //如果在 xml ImageView 节点中 没有设置 scaleType 那么默认在构造函数
中进行了初始化为  mScaleType = ScaleType.FIT_CENTER; 
   switch (view.getScaleType()) {
   .....
    case FIT_CENTER:
    case FIT_START:
    case FIT_END:
     //这里用到了克隆(原型设计模式),选择一个 居中合适 显示的方案,同学
们会发现,到处都是设计模式,它不是为了装B哦
     requestOptions =
requestOptions.clone().optionalFitCenter();
     break;
   ....
  }
 }
  //调用 into 重载函数,创建一个 ViewTarget
  return into(
  //调用 buildImageViewTarget 构建一个 ImageView 类型的
Target(Bitmap/Drawable)
    glideContext.buildImageViewTarget(view, transcodeClass),
    /*targetListener=*/ null,
    requestOptions,
    Executors.mainThreadExecutor());
}

上面代码就两大步:
第一步:先拿到当前 ImageView getScaleType 类型的属性,然后重新 clone 一个进
行配置;
第二步:调用 into 重载继续构建;
同学们先来看下 glideContext.buildImageViewTarget 是怎么构建出来
ImageViewTarget 的:

@NonNull
 public <X> ViewTarget<ImageView, X> buildImageViewTarget(
   @NonNull ImageView imageView, @NonNull Class<X>
transcodeClass) {
  //调用 工厂模式 根据 transcodeClass 生成出一个对应的
ImageViewTarget
  return imageViewTargetFactory.buildTarget(imageView,
transcodeClass);
}
public class ImageViewTargetFactory {
 @NonNull
 @SuppressWarnings("unchecked")
 public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull
ImageView view,
   @NonNull Class<Z> clazz) {
  //如果目标的编码类型属于 Bitmap 那么就创建一个 Bitmap 类型的
ImageViewTarget
  if (Bitmap.class.equals(clazz)) {
   return (ViewTarget<ImageView, Z>) new
BitmapImageViewTarget(view);
  如果目标的编码类型属于 Drawable 那么就创建一个 Drawable 类型的
ImageViewTarget
 } else if (Drawable.class.isAssignableFrom(clazz)) {
   return (ViewTarget<ImageView, Z>) new
DrawableImageViewTarget(view);
 } else {
   throw new IllegalArgumentException(
     "Unhandled class: " + clazz + ", try .as*
(Class).transcode(ResourceTranscoder)");
 }
}
}

上面 生产 Target 的时候注意一下,只要调用了  asBitmap 才会执行生
产 BitmapImageViewTarget ,所以这里我们关注 Drawable 类型就行了,我们就先
简单看看这个 target 内部怎么实现的

public class DrawableImageViewTarget extends
ImageViewTarget<Drawable> {
 public DrawableImageViewTarget(ImageView view) {
  super(view);
}
 @SuppressWarnings({"unused", "deprecation"})
 @Deprecated
 public DrawableImageViewTarget(ImageView view, boolean
waitForLayout) {
  super(view, waitForLayout);
}
 @Override
 protected void setResource(@Nullable Drawable resource) {
  view.setImageDrawable(resource);
}
}

从上面代码可以知道 DrawableImageViewTarget 继承的是
ImageViewTarget 重写的 setResource 函数,实现了显示 Drawable 图片的逻辑,
好了,这里先有个印象就行,我们只管主线流程,支线细节先跳读,最后会讲到怎么
调用的。继续 into 重载

private <Y extends Target<TranscodeType>> Y into(
   @NonNull Y target,
   @Nullable RequestListener<TranscodeType> targetListener,
   BaseRequestOptions<?> options,
   Executor callbackExecutor) {
  Preconditions.checkNotNull(target);
  //这里的 isModelSet 是在 load 的时候赋值为 true 的,所以不会抛异常
  if (!isModelSet) {
   throw new IllegalArgumentException("You must call #load()
before calling #into()");
 }
//为这个 http://xxx.png 生成一个 Glide request 请求
  Request request = buildRequest(target, targetListener,
options, callbackExecutor);
//相当于拿到上一个请求
  Request previous = target.getRequest();
  //下面的几行说明是否与上一个请求冲突,一般不用管 直接看下面 else 判断
  if (request.isEquivalentTo(previous)
    && !isSkipMemoryCacheWithCompletePreviousRequest(options,
previous)) {
   request.recycle();
   if (!Preconditions.checkNotNull(previous).isRunning()) {
    previous.begin();
  }
   return target;
}
//清理掉目标请求管理
  requestManager.clear(target);
  //重新为目标设置一个 Glide request 请求
  target.setRequest(request);
  //最后是调用 RequestManager 的 track 来执行目标的 Glide request 请
求
  requestManager.track(target, request);
  return target;
}

以上核心就两个点:
第一点:为 target buildRequest 构建一个 Glide request 请求;
第二点:将构建出来的 Request 交于 RequestManager 来执行

private Request buildRequest(
   Target<TranscodeType> target,
   @Nullable RequestListener<TranscodeType> targetListener,
   BaseRequestOptions<?> requestOptions,
   Executor callbackExecutor) {
  return buildRequestRecursive(
    target,
    targetListener,
    /*parentCoordinator=*/ null,
    transitionOptions,
    requestOptions.getPriority(),
    requestOptions.getOverrideWidth(),
    requestOptions.getOverrideHeight(),
    requestOptions,
    callbackExecutor);
}
private Request obtainRequest(
   Target<TranscodeType> target,
   RequestListener<TranscodeType> targetListener,
   BaseRequestOptions<?> requestOptions,
   RequestCoordinator requestCoordinator,
   TransitionOptions<?, ? super TranscodeType>
transitionOptions,
Priority priority,
   int overrideWidth,
   int overrideHeight,
   Executor callbackExecutor) {
  return SingleRequest.obtain(
    context,
    glideContext,
    model,
    transcodeClass,
    requestOptions,
    overrideWidth,
    overrideHeight,
    priority,
    target,
    targetListener,
    requestListeners,
    requestCoordinator,
    glideContext.getEngine(),
    transitionOptions.getTransitionFactory(),
    callbackExecutor);
}

最后我们发现是  SingleRequest.obtain 来为我们构建的 Request 请求对
象,开始只是初始化一些配置属性,下面我们就来找 begin 开始的地方, 先来看下
track 函数执行:

//这里对当前 class 加了一个同步锁避免线程引起的安全性 
synchronized void track(@NonNull Target<?> target, @NonNull
Request request) {
//添加一个目标任务 
targetTracker.track(target);
//执行 Glide request
  requestTracker.runRequest(request);
}
//这里对当前 class 加了一个同步锁避免线程引起的安全性 
synchronized void track(@NonNull Target<?> target, @NonNull
Request request) {
//添加一个目标任务 
targetTracker.track(target);
//执行 Glide request
  requestTracker.runRequest(request);
}
public void runRequest(@NonNull Request request) {
  //添加一个请求
  requests.add(request);
  //是否暂停
  if (!isPaused) {
   //没有暂停,开始调用 Request begin 执行
   request.begin();
 } else {
   //如果调用了 暂停,清理请求
   request.clear();
   pendingRequests.add(request);
 }
}

上面的逻辑是先为  requests 添加一个请求,看看是否是停止状态,如果不是就调
用  request.begin(); 执行。
这里的  Request 是一个接口,通过之前我们讲到  buildRequest 函数可知
Request 的实现类是  SingleRequest 我们就直接看它的  begin 函数.

@Override
 public synchronized 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));
 }
}

我们直接看 onSizeReady:

public synchronized void onSizeReady(int width, int height) {
  stateVerifier.throwIfRecycled();
 ....//都是一些初始化状态,配置属性,我们不用管。
  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,
      callbackExecutor);
}

load:

public synchronized <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,
   Executor callbackExecutor) {
  //拿到缓存或者请求的 key
  EngineKey key = keyFactory.buildKey(model, signature, width,
height, transformations,
    resourceClass, transcodeClass, options);
//根据 key 拿到活动缓存中的资源
  EngineResource<?> active = loadFromActiveResources(key,
isMemoryCacheable);
  //如果 ActiveResources 活动缓存中有就回调出去
  if (active != null) {
   cb.onResourceReady(active, DataSource.MEMORY_CACHE);
 return null;
 }
  //尝试从 LruResourceCache 中找寻这个资源
  EngineResource<?> cached = loadFromCache(key,
isMemoryCacheable);
  if (cached != null) {
   //如果内存缓存 Lru 中资源存在回调出去
   cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
   return null;
 }
  //------------- 走到这里说明活动缓存 跟内存 缓存都没有找到 ----------
-
 
  //根据 Key 看看缓存中是否正在执行
  EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
  if (current != null) {
   //如果正在执行,把数据回调出去
   current.addCallback(cb, callbackExecutor);
   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);
//把当前需要执行的 key 添加进缓存
  jobs.put(key, engineJob);
//执行任务的回调
  engineJob.addCallback(cb, callbackExecutor);
  //开始执行。
  engineJob.start(decodeJob);
  return new LoadStatus(cb, engineJob);
}

通过  engine.load 这个函数里面的逻辑,同学们我们可以总结3点:
1. 先构建请求或者缓存 KEY ;
2. 根据 KEY 从内存缓存中查找对应的资源数据(ActiveResources(活动缓存,内部
是一个 Map 用弱引用持有),LruResourceCache),如果有就回调 对应监听的
onResourceReady 表示数据准备好了。
3. 从执行缓存中查找对应 key 的任务
1. 如果找到了,就说明已经正在执行了,不用重复执行。
2. 没有找到,通过 EngineJob.start 开启一个新的请求任务执行。
同学们下面我们就来看下  engineJob.start 具体执行逻辑:

public synchronized void start(DecodeJob<R> decodeJob) {
  this.decodeJob = decodeJob;
  //拿到 Glide 执行的线程池
  GlideExecutor executor = decodeJob.willDecodeFromCache()
    ? diskCacheExecutor
   : getActiveSourceExecutor();
  //开始执行
  executor.execute(decodeJob);
}

通过  DecodeJob 源码得知,它是实现的  Runnable 接口,这里 GlideExecutor 线程
池开始执行,就会启动 DecodeJob 的 run 函数,我们跟踪 run 的实现:

class DecodeJob<R> implements
DataFetcherGenerator.FetcherReadyCallback,
  Runnable,
  Comparable<DecodeJob<?>>,
  Poolable {
  
   // 线程执行调用 run
   @Override
   public void run() {
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)",
model);
    DataFetcher<?> localFetcher = currentFetcher;
    try {
     //是否取消了当前请求
     if (isCancelled) {
      notifyFailed();
      return;
    }
     //执行
     runWrapped();
   } catch (CallbackException e) {
    .....//一些错误回调
  }
 }

分析runWrapped:

private void runWrapped() {
  switch (runReason) {
   case INITIALIZE:
    //获取资源状态
    stage = getNextStage(Stage.INITIALIZE);
    //根据当前资源状态,获取资源执行器
    currentGenerator = getNextGenerator();
    //执行
    runGenerators();
    break;
  ...
 }
}
 private Stage getNextStage(Stage current) {
  switch (current) {
   case INITIALIZE:
    //如果外部调用配置了资源缓存策略,那么返回 Stage.RESOURCE_CACHE
   //否则继续调用 Stage.RESOURCE_CACHE 执行。
    return diskCacheStrategy.decodeCachedResource()
      ? Stage.RESOURCE_CACHE :
getNextStage(Stage.RESOURCE_CACHE);
   case RESOURCE_CACHE:
    //如果外部配置了源数据缓存,那么返回 Stage.DATA_CACHE
    //否则继续调用 getNextStage(Stage.DATA_CACHE)
    return diskCacheStrategy.decodeCachedData()
      ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
   case DATA_CACHE:
    //如果只能从缓存中获取数据,则直接返回 FINISHED,否则,返回SOURCE。
    //意思就是一个新的资源
    return onlyRetrieveFromCache ? Stage.FINISHED :
Stage.SOURCE;
   case SOURCE:
   case FINISHED:
    return Stage.FINISHED;
   default:
    throw new IllegalArgumentException("Unrecognized stage: "
+ current);
 }
}

通过上面代码可以知道,我们在找资源的执行器,这里由于我们没有在外部配置缓存
策略所以,直接从源数据加载,看下面代码:

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

由于我们什么都没有配置,返回的是  SourceGenerator 源数据执行
器。继续下面代码执行:

private void runGenerators() {
  currentThread = Thread.currentThread();
  startFetchTime = LogTime.getLogTime();
  boolean isStarted = false;
  //判断是否取消,是否开始
  //调用 DataFetcherGenerator.startNext() 判断是否是属于开始执行的任
务
  while (!isCancelled && currentGenerator != null
    && !(isStarted = currentGenerator.startNext())) {
  ....
}

上面代码先看  currentGenerator.startNext() 这句代码,
DataFetcherGenerator 是一个抽象类,那么这里执行的实现类是哪一个,可以参
考下面说明:
Stage.RESOURCE_CACHE【状态标记】 ---- 从磁盘中获取缓存的资源数据【作用】 -
-- ResourceCacheGenerator【执行器】
Stage.DATA_CACHE【状态标记】 ---- 从磁盘中获取缓存的源数据【作用】 ---
DataCacheGenerator【执行器】
Stage.SOURCE【状态标记】 --- 一次新的请求任务 --- SourceGenerator【执行器】
因为这里我们没有配置缓存,那么直接看  SourceGenerator

@Override
 public boolean startNext() {
...
  loadData = null;
  boolean started = false;
  while (!started && hasNextModelLoader()) {
   //获取一个 ModelLoad 加载器
   loadData = helper.getLoadData().get(loadDataListIndex++);
   if (loadData != null
     &&
(helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.g
etDataSource())
     ||
helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
    started = true;
    //使用加载器中的 fetcher 根据优先级加载数据
    loadData.fetcher.loadData(helper.getPriority(), this);
  }
 }
  return started;
}

 helper.getLoadData() 获取的是一个什么样的加载器,我们可以先
猜一下,因为没有配置任何缓存,所以可以猜得到是 http 请求了,那么是不是猜测
的那样的

 List<LoadData<?>> getLoadData() {
  if (!isLoadDataSet) {
   isLoadDataSet = true;
   loadData.clear();
   //从 Glide 注册的 Model 来获取加载器(注册是在 Glide 初始化的时候通
过 registry
   // .append()添加的)
   List<ModelLoader<Object, ?>> modelLoaders =
glideContext.getRegistry().getModelLoaders(model);
 
   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;
}

首先拿到一个加载器的容器,加载器是在 Glide 初始化的时候 通过
Registry.append() 添加的,所以,
ModelLoad 的实现类是  HttpGlideUrlLoader 加载器,我们看下它的具体实现:

@Override
 public LoadData<InputStream> buildLoadData(@NonNull GlideUrl
model, int width, int height,
   @NonNull Options options) {
  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));
}

这里看到是返回的一个 HttpUrlFetcher 给加载器。加载器我们拿到了,现在开始
加载,返回到刚刚的源码,请看下面:

class DataCacheGenerator implements DataFetcherGenerator,
  DataFetcher.DataCallback<Object> {
  
   //挑重要代码
   @Override
 public boolean startNext() {
....
  while (!started && hasNextModelLoader()) {
   ModelLoader<File, ?> modelLoader =
modelLoaders.get(modelLoaderIndex++);
   loadData =
     modelLoader.buildLoadData(cacheFile, helper.getWidth(),
helper.getHeight(),
       helper.getOptions());
   if (loadData != null &&
helper.hasLoadPath(loadData.fetcher.getDataClass())) {
    started = true;
   //通过拿到的加载器,开始加载数据
    loadData.fetcher.loadData(helper.getPriority(), this);
  }
 }
  return started;
} 
}

这里拿到的加载器是 HttpUrlFetcher 所以我们直接看它的
loadData 实现:

@Override
 public void loadData(@NonNull Priority priority,
   @NonNull DataCallback<? super InputStream> callback) {
  long startTime = LogTime.getLogTime();
  try {
   //http 请求,返回一个 InputStream 输入流
   InputStream result =
loadDataWithRedirects(glideUrl.toURL(), 0, null,
glideUrl.getHeaders());
   //将 InputStream 以回调形式回调出去
   callback.onDataReady(result);
 } catch (IOException e) {
   callback.onLoadFailed(e);
 } finally {
  ...
 }
}

loadDataWithRedirects 这个函数是怎么生成的一个InputStream :

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 {
   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);
  urlConnection.setInstanceFollowRedirects(false);
  urlConnection.connect();
  stream = urlConnection.getInputStream();
  if (isCancelled) {
   return null;
 }
  final int statusCode = urlConnection.getResponseCode();
  if (isHttpOk(statusCode)) {
   return getStreamForSuccessfulRequest(urlConnection);
 }
 ...//抛的异常我们暂时先不管
}

这里是 HttpURLConnection 作为 Glide 底层
成网络请求的。请求成功之后直接返回的是一个输入流,最后会通过  onDataReady
回调到 DecodeJob onDataFetcherReady 函数中。回调到
SourceGenerator :

@Override
 public void onDataReady(Object data) {
  DiskCacheStrategy diskCacheStrategy =
helper.getDiskCacheStrategy();
  if (data != null &&
diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource(
))) {
   dataToCache = data;
   cb.reschedule();
 } else {
   cb.onDataFetcherReady(loadData.sourceKey, data,
loadData.fetcher,
     loadData.fetcher.getDataSource(), originalKey);
 }
}

这里会有 else 因为我们没有配置缓存,继续回调:

class DecodeJob<R> implements
DataFetcherGenerator.FetcherReadyCallback,
  Runnable,
  Comparable<DecodeJob<?>>,
  Poolable {
  ...
   @Override
   public void onDataFetcherReady(Key sourceKey, Object data,
DataFetcher<?> fetcher,
     DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey; //当前返回数据的 key
    this.currentData = data; //返回的数据
    this.currentFetcher = fetcher; //返回的数据执行器,这里可以理解
为 HttpUrlFetcher
    this.currentDataSource = dataSource; //数据来源 url
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
     runReason = RunReason.DECODE_DATA;
     callback.reschedule(this);
   } else {
   
 GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
     try {
      //解析返回回来的数据
      decodeFromRetrievedData();
    } finally {
      GlideTrace.endSection();
   }
   }
  } 
  ...
 }
 //解析返回的数据
 private void decodeFromRetrievedData() {
  Resource<R> resource = null;
  try {
   // 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream ,
currentDataSource
   resource = decodeFromData(currentFetcher, currentData,
currentDataSource);
 } catch (GlideException e) {
   e.setLoggingDetails(currentAttemptingKey,
currentDataSource);
   throwables.add(e);
 }
  //解析完成后,通知下去
  if (resource != null) {
   notifyEncodeAndRelease(resource, currentDataSource);
 } else {
   runGenerators();
 }
}

继续跟 decodeFromData 看看怎么解析成 Resource 的:

private <Data> Resource<R> decodeFromData(DataFetcher<?>
fetcher, Data data,
   DataSource dataSource) throws GlideException {
 ... 
   Resource<R> result = decodeFromFetcher(data, dataSource);
  ....
   return result;
 } finally {
   fetcher.cleanup();
 }
}
 @SuppressWarnings("unchecked")
 private <Data> Resource<R> decodeFromFetcher(Data data,
DataSource dataSource)
   throws GlideException {
 //获取当前数据类的解析器 LoadPath
  LoadPath<Data, ?, R> path =
decodeHelper.getLoadPath((Class<Data>) data.getClass());
  //通过 LoadPath 解析器来解析数据
  return runLoadPath(data, dataSource, path);
}
 private <Data, ResourceType> Resource<R> runLoadPath(Data data,
DataSource dataSource,
   LoadPath<Data, ResourceType, R> path) throws GlideException
{
  Options options = getOptionsWithHardwareConfig(dataSource);
 
  //因为这里返回的是一个 InputStream 所以 这里拿到的是
InputStreamRewinder
  DataRewinder<Data> rewinder =
glideContext.getRegistry().getRewinder(data);
  try {
   //将解析资源的任务转移到 Load.path 方法中
   return path.load(
     rewinder, options, width, height, new
DecodeCallback<ResourceType>(dataSource));
 } finally {
   rewinder.cleanup();
 }
}

为了解析数据首先构建一个 LoadPath, 然后创建一个
InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作放到了
LoadPath.load 方法中 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值