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

Glide.with(imageView.context).load(url).into(imageView)

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

分别传递了3个参数

  • context主要用于生成framgnet控制glide加载生命周期
  • 基于url生成key,找到缓存中对应的图片资源
  • 有了图片资源后,加载到imageView中

生命周期的控制——RequestManager

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

getRetriever中获取glide的RequestManagerRetriever

  • 若glide为null,则会用单例模式构造
  • RequestManagerRetriever

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

  • 这里的生命周期和androidX中的不是同一个,但作用类似
  • 同一个context只会生成一个RequestManagerFragment/SupportRequestManagerFragment,并且只有这一个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,在构建的时候注册监听.

  • 除了注册自身的监听,还有个ConnectivityMonitor,在有网络权限时,默认实现为DefaultConnectivityMonitor.DefaultConnectivityMonitor在接受到onStart事件时,会注册一个监听网络状态的广播,onStop时注销.当无网状态切换到有网的时候,广播便会执行requestTracker.restartRequests(),开始处理请求.

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 负责跟踪Request
  • TargetTracker 负责跟踪Target

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

private > Y into(
      @NonNull Y target,
      @Nullable RequestListener 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继承LifecycleListener,会被TargetTracker控制;Target有很多实现,这里transcodeClass对应的是Drawable.class,生成DrawableImageViewTarget

    public ViewTarget into(@NonNull ImageView view) {
        
            ...
    
        return into(
            glideContext.buildImageViewTarget(view, transcodeClass),
            /*targetListener=*/ null,
            requestOptions,
            Executors.mainThreadExecutor());
      }
    
    public class ImageViewTargetFactory {
      @NonNull
      @SuppressWarnings("unchecked")
      public  ViewTarget buildTarget(
          @NonNull ImageView view, @NonNull Class clazz) {
        if (Bitmap.class.equals(clazz)) {
          return (ViewTarget) new BitmapImageViewTarget(view);
        } else if (Drawable.class.isAssignableFrom(clazz)) {
          return (ViewTarget) new DrawableImageViewTarget(view);
        } else {
          throw new IllegalArgumentException(
              "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
        }
      }
    }
    
  • Request的基本实现是SingleRequest,同样会被RequestTracker控制

    private Request obtainRequest(
          Object requestLock,
          Target target,
          RequestListener targetListener,
          BaseRequestOptions requestOptions,
          RequestCoordinator requestCoordinator,
          TransitionOptions transitionOptions,
          Priority priority,
          int overrideWidth,
          int overrideHeight,
          Executor callbackExecutor) {
        return SingleRequest.obtain(
            context,
            glideContext,
            requestLock,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            targetListener,
            requestListeners,
            requestCoordinator,
            glideContext.getEngine(),
            transitionOptions.getTransitionFactory(),
            callbackExecutor);
      }
    

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

public RequestBuilder load(@Nullable Object model) {
    return asDrawable().load(model);
}
public RequestBuilder asDrawable() {
    return as(Drawable.class);
}
public  RequestBuilder as(
      @NonNull Class 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中取数据)

  • activeResources 没有大小限制.保存活跃的图片资源.
  • cache 有大小限制.保存不展示的图片资源
  • 受生命周期控制,当RequestManagerFragment/SupportRequestManagerFragment销毁的时候,从activeResources中remove添加到cache中

→waitForExistingOrStartNewJob

  • 从activeResources/cache中没取到数据时,则执行这个方法,如果任务已经存在,则不重复创建,只添加回调

  • 若任务不存在,则构建EngineJob和DecodeJob,并在EngineJob中启动DecodeJob

    public synchronized void start(DecodeJob decodeJob) {
        this.decodeJob = decodeJob;
        GlideExecutor executor =
            decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
        executor.execute(decodeJob);
      }
    
  • 这里利用线程池执行DecodeJob(DecodeJob本身继承Runnable)

  • decodeJob.willDecodeFromCache() 会根据diskCacheStrategy来判断使用那个线程池

    boolean willDecodeFromCache() {
        Stage firstStage = getNextStage(Stage.INITIALIZE);
        return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
    }
    
    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);
        }
      }
    
  • diskCacheStrategy对象得追溯到Glide构造的时候,有默认实现,也有set方法.共有5种类型,ALL/NONE/DATA/RESOURCE/AUTOMATIC.默认实现为AUTOMATIC.

    public final class GlideBuilder {
    
            private RequestOptionsFactory defaultRequestOptionsFactory =
          new RequestOptionsFactory() {
            @NonNull
            @Override
            public RequestOptions build() {
              return new RequestOptions();
            }
        };
    
            public GlideBuilder setDefaultRequestOptions(@Nullable final RequestOptions requestOptions) {
            return setDefaultRequestOptions(
            new RequestOptionsFactory() {
              @NonNull
              @Override
              public RequestOptions build() {
                return requestOptions != null ? requestOptions : new RequestOptions();
              }
            });
          }
    }
    
  • 通过上面的分析可知,当设置的DiskCacheStrategy == AUTOMATIC == RESOURCE == ALL的时候 firstStage == Stage.RESOURCE_CACHE. DiskCacheStrategy == DATA 时 firstStage == Stage.DATA_CACHE,便会启动diskCacheExecutor.

    • 线程池数量为1
  • 只有DiskCacheStrategy == NONE,才会启动getActiveSourceExecutor.useUnlimitedSourceGeneratorPool和useAnimationPool默认为false,则会启动sourceExecutor

    • 线程池数量由CPU核心数决定,最小为4个
    private GlideExecutor getActiveSourceExecutor() {
        return useUnlimitedSourceGeneratorPool
            ? sourceUnlimitedExecutor
            : (useAnimationPool ? animationExecutor : sourceExecutor);
    }
    
    public static int calculateBestThreadCount() {
        if (bestThreadCount == 0) {
          bestThreadCount =
              Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, RuntimeCompat.availableProcessors());
        }
        return bestThreadCount;
      }
    

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

EngineJob.notifyCallbacksOfResult

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

加载过程——DecodeJob

  • ResourceCacheGenerator 从内存中获取数据
  • DataCacheGenerator 从本地缓存中获取,并存储到内存中
  • SourceGenerator 从网络获取图片,并存储到本地

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 根据打印内容判断加载源

  • Started new load 磁盘或者网络
  • Loaded resource from active resources
  • Loaded resource from cache

DecodeJob|Engine|OkHttpLoadImg|PrintingEventListener|SourceGenerator|loadImg

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

你可能感兴趣的:(Glide加载一张网图时发生了啥)