Android开发经验谈Android技术知识Android开发

Glide加载一张网图时发生了啥

2020-05-08  本文已影响0人  Raven
Glide.with(imageView.context).load(url).into(imageView)

这一串代码是加载图片的最简形式.

分别传递了3个参数

生命周期的控制——RequestManager

  @NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }

getRetriever中获取glide的RequestManagerRetriever

RequestManagerRetriever中通过对context类型的判断,生成RequestManagerFragment/SupportRequestManagerFragment.通过这个framgnet获取生命周期和RequestManagerTreeNode,生成RequestManager

RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    
        ...

    // If we're the application level request manager, we may be created on a background thread.
    // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
    // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
    // This should be entirely safe.
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);
        
        ...
  }

RequestManager本身继承LifecycleListener,在构建的时候注册监听.

RequestManager的onStart和onStop方法中,会针对requestTracker和targetTracker这两个对象操作

/**
   * Lifecycle callback that registers for connectivity events (if the
   * android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused
   * requests.
   */
  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  /**
   * Lifecycle callback that unregisters for connectivity events (if the
   * android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
   */
  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }

RequestTracker和TargetTracker都是对数组进行操作,既然是数组,通过查看对数组操作的函数,最后定位到RequestBuilder.into函数中

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
        
        Request request = buildRequest(target, targetListener, options, callbackExecutor);
        ...

    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

加载请求的构建——RequestBuilder

在into方法中,构建了target与request

上面构建Target时,之所以说transcodeClass == Drawable.class.是因为transcodeClass的类型由Glide.load函数决定的.

public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
}
public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
}

加载的逻辑

RequestManager的onStart执行时,初始status == Status.PENDING

public void begin() {
    synchronized (requestLock) {

            ...

      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        target.getSize(this);
      }

    }
  }

target.getSize(target为DrawableImageViewTarget,getSize为基类ViewTarget函数)→

SizeDeterminer.getSize(获取宽高,若宽高无效,通过注册ViewTreeObserver,在onPreDraw中获取宽高,获取到有效数据后,回调SingleRequest.onSizeReady)→

SingleRequest.onSizeReady→

Engine.load(这个时候会通过Glide.load等参数构建EngineKey,通过key去activeResources/cache中取数据)

→waitForExistingOrStartNewJob

DecodeJob执行完成后,会回调EngineJob.onResourceReady→

EngineJob.notifyCallbacksOfResult

  1. CallResourceReady.run()→SingleRequest.onResourceReady→target.onResourceReady→设置资源
  2. Engine.onEngineJobComplete(将资源存储到activeResources中)

加载过程——DecodeJob

run→

runWrapped(初始化时,runReason == INITIALIZE)→

getNextStage(根据diskCacheStrategy,更新Stage)→

getNextGenerator(根据stage,获取需要执行的generator)→

runGenerators(while循环执行generator.startNext)→

reschedule(当循环到stage =SOURCE时执行,currentGenerator = SourceGenerator 。交给线程池,重新run)→

run→

runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→

SourceGenerator.startNext(初始逻辑,获取loadData中的fetcher,执行fetcher的加载逻辑,fetcher执行成功后)→

SourceGenerator.onDataReady→

DecodeJob.reschedule(重新调度)→

run→

runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→

SourceGenerator.startNext(写入本地文件逻辑)→

SourceGenerator.cacheData→

DataCacheGenerator.startNext(找到对应的LoadData,加载数据,加载完成执行callback onDataReady,再接口回调至SourceGenerator.onDataFetcherReady,再接口回调至DecodeJob.onDataFetcherReady)→

reschedule(runReason = RunReason.DECODE_DATA,重新调度)→

run→

runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→

decodeFromRetrievedData→

decodeFromData(根据currentData类型,currentDataSource数据源类型,在Registry中找到对应的decoder和transcoder,并组建出decodePaths;根据decodePaths组建LoadPath;根据LoadPath获取Resource<>,正常为LazyBitmapDrawableResource类型)→

notifyEncodeAndRelease→

notifyComplete→触发EngineJob.onResourceReady

总结

  1. Glide在加载时,会生成全局唯一的glide和engine.
  2. 每个activity加载图片时,都会额外创建一个不可见的fragmnt,用于控制生命周期,基于此生成requestManager.
  3. 每个加载请求都会生成target与request,target中收集了view信息及view资源类型.在target确认好view的宽高后,会通过request触发engine的加载逻辑.
  4. engine会尝试从activeResources和cache中加载数据,未成功,便会创建engineJob和decodeJob.
  5. engineJob会启动decodeJob,尝试从ResourceCacheGenerator/DataCacheGenerator/SourceGenerator中获取数据.
  6. 取得数据后,便交由target设置资源,同时保存到engine的activeResources中.
  7. 当activity销毁时,触发生命周期销毁逻辑,资源从activeResources中remove添加到cache中.

调试日志

adb shell setprop log.tag.Engine VERBOSE 根据打印内容判断加载源

DecodeJob|Engine|OkHttpLoadImg|PrintingEventListener|SourceGenerator|loadImg

关闭日志 adb shell setprop log.tag.Engine ERROR

上一篇 下一篇

猜你喜欢

热点阅读