Glide从磁盘加载图片资源的流程

本文深入解析Glide从磁盘加载图片的过程,涉及DecodeJob、EngineJob的线程池和ModelLoaderRegistry。当内存缓存未命中时,Glide通过DecodeJob的多个阶段从磁盘读取缓存或网络加载图片,最终写入磁盘和内存缓存,并通知Target显示。
摘要由CSDN通过智能技术生成

本文基于Android 【手撕Glide】–Glide缓存机制,进一步分析 DecodeJob#runWrapped 从磁盘中加载图片的过程。本文涉及到如何从网络加载图片,和写入 DATA 磁盘缓存、RESOURCE 磁盘缓存、ActiveResources 缓存的时机,以及如何从 ModelLoaderRegistry 中获取 ModelLoader。

前情提要: 在内存缓存没有命中🎯的时候,Engine 会创建 EngineJob 和 DecodeJob,在 EngineJob 的线程池中执行 DecodeJob,执行到 DecodeJob#runWrapped 来加载图片 (Engine#load -> Engine#waitForExistingOrStartNewJob -> EngineJob#start -> DecodeJob#runWrapped)。

DecodeJob 主要过程

  private void runWrapped() {
   
    switch (runReason) {
   
      case INITIALIZE: // 初始状态,依次访问磁盘缓存 RESOURCE 和 DATA
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE: // 网络下载图片成功时,会走到这里
        runGenerators();
        break;
      case DECODE_DATA: // 成功加载数据源后,解码到 Resource
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

  private void runGenerators() {
   
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
    
      // startNext 返回 false 就继续到下一个 State 和生成器❤️
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
   
        reschedule(); // 从网络中加载前,这里要切换线程池啦❤️
        return;
      }
    }
    // We've run out of stages and generators, give up.
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
   
      notifyFailed();
    }

    // Otherwise a generator started a new load and we expect to be called back in
    // onDataFetcherReady.
  }
  1. 初始 Stage 为 INITIALIZE,那么下一个 Stage 为 RESOURCE_CACHE,下一个生成器为 ResourceCacheGenerator,主要在其 #startNext 方法,创建 ResourceCacheKey,从磁盘中读取缓存,一开始当然没有缓存,那么 modelLoaders 为 null,导致马上返回 false;
  2. 下一个 Stage 为 DATA_CACHE,下一个生成器为 DataCacheGenerator,在其 #startNext 方法,创建 DataCacheKey,从磁盘中读取缓存,一开始也没有缓存,那么 modelLoaders 为 null,导致马上返回 false;
  3. 下一个 Stage 为 SOURCE,下一个生成器为 SourceGenerator,在其 #startNext 方法,一开始 dataToCache 为 null,sourceCacheGenerator 为 null,在这里终于去获取 ModelLoader,假设我们是设置 “https://picture.jpg" 这样的图片网络地址,那么最后从 Glide 配置的 ModelLoaderRegistry 中解析出来的就是 HttpGlideUrlLoader,并根据我们的网络地址字符串创建了 GlideUrl 对象作为 sourceKey,HttpGlideUrlLoader 会通过 HttpUrlFetcher 从网络加载图片
  // HttpUrlFetcher
  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));
      }
    }
  }
  1. 加载成功,会从网络连接中得到 InputStream 回调到 SourceGenerator#onDataReadyInternal,将 InputStream 保存到 dataToCache ,最后调用 DecodeJob#reschedule
  public void reschedule() {
   
    runReason 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值