美文网首页
Glide源码(二)

Glide源码(二)

作者: JackyWu15 | 来源:发表于2020-01-13 19:32 被阅读0次

    接着上一篇,with方法获取到RequestManager 对象,它实现了LifecycleListener接口,这意味着,页面生命周期的触发会通知到RequestManager 类,但根据上一篇分析,在此之前,它必须先被添加到ActivityFragmentLifecycle的成员变量lifecycleListeners 集合中 ,我们先看它的构造方法。

    public class RequestManager implements LifecycleListener,
        ModelTypes<RequestBuilder<Drawable>> {
    
      private final ConnectivityMonitor connectivityMonitor;
      private final Handler mainHandler = new Handler(Looper.getMainLooper());
      private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;
      
      private final Runnable addSelfToLifecycle = new Runnable() {
        @Override
        public void run() {
          lifecycle.addListener(RequestManager.this);
        }
      };
      public RequestManager(
          @NonNull Glide glide, @NonNull Lifecycle lifecycle,
          @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
        this(
            glide,
            lifecycle,
            treeNode,
            new RequestTracker(),
            glide.getConnectivityMonitorFactory(),
            context);
      }
    
      RequestManager(
          Glide glide,
          Lifecycle lifecycle,
          RequestManagerTreeNode treeNode,
          RequestTracker requestTracker,
          ConnectivityMonitorFactory factory,
          Context context) {
        this.glide = glide;
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        this.context = context;
        //网络监听器
        connectivityMonitor =
            factory.build(
                context.getApplicationContext(),
                new RequestManagerConnectivityListener(requestTracker));
    
        //后台线程,切到主线程中添加
        if (Util.isOnBackgroundThread()) {
          mainHandler.post(addSelfToLifecycle);
        } else {
          //添加自己到ActivityFragmentLifecycle的集合中
          lifecycle.addListener(this);
        }
        //添加网络监听器
        lifecycle.addListener(connectivityMonitor);
    
        defaultRequestListeners =
            new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
        setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
    
        //保存到glide的成员列表中
        glide.registerRequestManager(this);
      }
    
    }
    
    

    可以看出,ConnectivityMonitor 也实现了LifecycleListener接口,因为它也被添加到lifecycleListeners 集合中,跟随Framgent的生命周期回调。

    获取到RequestManager对象后,将调用load方法。

    public class RequestManager implements LifecycleListener,
        ModelTypes<RequestBuilder<Drawable>> {
    
        public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
          return asDrawable().load(bitmap);
        }
    
        public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
          return asDrawable().load(drawable);
        }
    
        public RequestBuilder<Drawable> load(@Nullable String string) {
          return asDrawable().load(string);
        }
    
        //转码后的类型为Bitmap.class
        public RequestBuilder<Bitmap> asBitmap() {
          return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
        }
    
        //转码后的类型为Drawable.class
        public RequestBuilder<Drawable> asDrawable() {
          return as(Drawable.class);
        }
    
        //获取RequestBuilder
        public <ResourceType> RequestBuilder<ResourceType> as(
        @NonNull Class<ResourceType> resourceClass) {
        // resourceClass 就是最终要转码的类型
          return new RequestBuilder<>(glide, this, resourceClass, context);
        }
    
    }
    

    适配不同资源的加载,load有多个重载方法,他们最终都通过as方法来获取一个RequestBuilder对象,后面一连串的链式调用,都将通过这个对象的方法作为入口来执行。和RequestManager 的load方法一样,RequestBuilder的load也有许多重载方法,我们以网络地址加载为例来做分析。

    public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
        implements Cloneable,
        ModelTypes<RequestBuilder<TranscodeType>> {
    
      private Object model;
      private boolean isModelSet;
    
      //加载网络地址
      public RequestBuilder<TranscodeType> load(@Nullable String string) {
          return loadGeneric(string);
        }
    
      //将地址封装成model
      private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
        this.model = model;
        isModelSet = true;
        return this;
      }
    
    
    }
    

    在执行请求前,所有数据源都会被封装成一个model对象,它是Object类型的。

    load方法调用完成,便获得的一个RequestBuilder对象,接着通过它调用into方法。

    public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
        implements Cloneable,
        ModelTypes<RequestBuilder<TranscodeType>> {
    
        ......
    
      public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
        Util.assertMainThread();
        Preconditions.checkNotNull(view);
    
        BaseRequestOptions<?> requestOptions = this;
        if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
          // 根据裁剪配置options
          switch (view.getScaleType()) {
            case CENTER_CROP:
              requestOptions = requestOptions.clone().optionalCenterCrop();
              break;
            case CENTER_INSIDE:
              requestOptions = requestOptions.clone().optionalCenterInside();
              break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
              requestOptions = requestOptions.clone().optionalFitCenter();
              break;
            case FIT_XY:
              requestOptions = requestOptions.clone().optionalCenterInside();
              break;
            case CENTER:
            case MATRIX:
            default:
          }
        }
      
        return into(
            glideContext.buildImageViewTarget(view, transcodeClass),
            null,
            requestOptions,
            Executors.mainThreadExecutor());
          }
    
    }
    

    会根据我们在ImageView中设置的ScaleType类型,给requestOptions 配置裁剪类型。最后的into重载方法中,将调用buildImageViewTarget根据转码的类型来生成一个 ViewTarget,这个方法定义在GlideContext中。

    public class GlideContext extends ContextWrapper {
          ......
      private final ImageViewTargetFactory imageViewTargetFactory;
         ......
    
      public <X> ViewTarget<ImageView, X> buildImageViewTarget(
          @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
        return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
      }
    
    }
    

    在上一篇分析Glide的初始化时,ImageViewTargetFactory 这个图片显示目标对象工厂,已经在构造方法中创建出来了,同时还创建了GlideContext 对象,将ImageViewTargetFactory 传递给它。

    public class ImageViewTargetFactory {
      @NonNull
      @SuppressWarnings("unchecked")
      public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
          @NonNull Class<Z> clazz) {
        //Bitmap
        if (Bitmap.class.equals(clazz)) {
          return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
        //是否Drawable或其子类
        } 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)");
        }
      }
    }
    

    ViewTarget的子类有两种,在上面的RequestManager 类中虽然有多个as方法,但最终的转码类型只会有两类,即Bitmap类型或Drawable及其子类类型,我们加载网络地址,这里的ViewTarget将使用DrawableImageViewTarget,它继承ImageViewTarget,持有ImageView对象。

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

    看到setResource这个方法我们可以猜到,最终图片被显示到ImageView中,将通过它来完成。我们先回到RequestManager 重载的into方法。

    public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
        implements Cloneable,
        ModelTypes<RequestBuilder<TranscodeType>> {
    
    
      private <Y extends Target<TranscodeType>> Y into(
          @NonNull Y target,
          @Nullable RequestListener<TranscodeType> targetListener,
          BaseRequestOptions<?> options,
          Executor callbackExecutor) {
      
        //这里的Target就是DrawableImageViewTarget了
        Preconditions.checkNotNull(target);
    
        //是否设置了数据源,也就是url,在load中isModelSet已置为true
        if (!isModelSet) {
          throw new IllegalArgumentException("You must call #load() before calling #into()");
        }
    
        //Request类是一个接口,他抽象了Glide加载图片请求
        Request request = buildRequest(target, targetListener, options, callbackExecutor);
        //获取上一次的Request
        Request previous = target.getRequest();
    
        // 当前的target里有Request存在
        if (request.isEquivalentTo(previous)
            && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
          //回收刚新建的Request对象
          request.recycle();
          if (!Preconditions.checkNotNull(previous).isRunning()) {
                  //执行当前的Request
                  previous.begin();
          }
          //结束
          return target;
        }
        //清除target
        requestManager.clear(target);
        //Target中设置request
        target.setRequest(request);
        //执行request
        requestManager.track(target, request);
    
        return target;
      }
    }
    

    Request用来发出加载图片的请求,通过buildRequest来构建,然后将通过RequestManager对象来执行这个请求。我们先看构建过程。

    public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
        implements Cloneable,
        ModelTypes<RequestBuilder<TranscodeType>> {
    
    
        private Request buildRequest(
          Target<TranscodeType> target,
          @Nullable RequestListener<TranscodeType> targetListener,
          BaseRequestOptions<?> requestOptions,
          Executor callbackExecutor) {
        return buildRequestRecursive(
            target,
            targetListener,
             null,
            transitionOptions,
            requestOptions.getPriority(),
            requestOptions.getOverrideWidth(),
            requestOptions.getOverrideHeight(),
            requestOptions,
            callbackExecutor);
        }
    
    
        private Request buildRequestRecursive(
          Target<TranscodeType> target,
          @Nullable RequestListener<TranscodeType> targetListener,
          @Nullable RequestCoordinator parentCoordinator,
          TransitionOptions<?, ? super TranscodeType> transitionOptions,
          Priority priority,
          int overrideWidth,
          int overrideHeight,
          BaseRequestOptions<?> requestOptions,
          Executor callbackExecutor) {
    
        // 如果配置了错误请求则新建错误请求协调器
        ErrorRequestCoordinator errorRequestCoordinator = null;
        if (errorBuilder != null) {
          errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
          parentCoordinator = errorRequestCoordinator;
        }
    
      // 构造目标请求
        Request mainRequest =
            buildThumbnailRequestRecursive(
                target,
                targetListener,
                parentCoordinator,
                transitionOptions,
                priority,
                overrideWidth,
                overrideHeight,
                requestOptions,
                callbackExecutor);
    
        //如果没有配置错误请求则结束,否则继续下面代码构建错误时的备用请求
        if (errorRequestCoordinator == null) {
          return mainRequest;
        }
    
        int errorOverrideWidth = errorBuilder.getOverrideWidth();
        int errorOverrideHeight = errorBuilder.getOverrideHeight();
        if (Util.isValidDimensions(overrideWidth, overrideHeight)
            && !errorBuilder.isValidOverride()) {
          errorOverrideWidth = requestOptions.getOverrideWidth();
          errorOverrideHeight = requestOptions.getOverrideHeight();
        }
    
      // 错误时的备用请求
        Request errorRequest =
            errorBuilder.buildRequestRecursive(
                target,
                targetListener,
                errorRequestCoordinator,
                errorBuilder.transitionOptions,
                errorBuilder.getPriority(),
                errorOverrideWidth,
                errorOverrideHeight,
                errorBuilder,
                callbackExecutor);
        errorRequestCoordinator.setRequests(mainRequest, errorRequest);
        return errorRequestCoordinator;
      }
    
    
        private Request buildThumbnailRequestRecursive(
          Target<TranscodeType> target,
          RequestListener<TranscodeType> targetListener,
          @Nullable RequestCoordinator parentCoordinator,
          TransitionOptions<?, ? super TranscodeType> transitionOptions,
          Priority priority,
          int overrideWidth,
          int overrideHeight,
          BaseRequestOptions<?> requestOptions,
          Executor callbackExecutor) {
     
        if (thumbnailBuilder != null) {
              if (isThumbnailBuilt) {
            throw new IllegalStateException("You cannot use a request as both the main request and a "
                + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
          }
    
        // 设置 transitionOptions
          TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
              thumbnailBuilder.transitionOptions;
    
          if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
            thumbTransitionOptions = transitionOptions;
          }
    
          //优先级
          Priority thumbPriority = thumbnailBuilder.isPrioritySet()
              ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);
    
          //图片尺寸
          int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
          int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
          if (Util.isValidDimensions(overrideWidth, overrideHeight)
              && !thumbnailBuilder.isValidOverride()) {
            thumbOverrideWidth = requestOptions.getOverrideWidth();
            thumbOverrideHeight = requestOptions.getOverrideHeight();
          }
          
          // 缩略图请求协调器
          ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
    
          // 目标请求
          Request fullRequest =
              obtainRequest(
                  target,
                  targetListener,
                  requestOptions,
                  coordinator,
                  transitionOptions,
                  priority,
                  overrideWidth,
                  overrideHeight,
                  callbackExecutor);
          isThumbnailBuilt = true;
    
          // 缩略图的请求 
          Request thumbRequest =
              thumbnailBuilder.buildRequestRecursive(
                  target,
                  targetListener,
                  coordinator,
                  thumbTransitionOptions,
                  thumbPriority,
                  thumbOverrideWidth,
                  thumbOverrideHeight,
                  thumbnailBuilder,
                  callbackExecutor);
          isThumbnailBuilt = false;
          coordinator.setRequests(fullRequest, thumbRequest);
          return coordinator;
        } else if (thumbSizeMultiplier != null) {
          ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
          Request fullRequest =
              obtainRequest(
                  target,
                  targetListener,
                  requestOptions,
                  coordinator,
                  transitionOptions,
                  priority,
                  overrideWidth,
                  overrideHeight,
                  callbackExecutor);
          BaseRequestOptions<?> thumbnailOptions =
              requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
    
          Request thumbnailRequest =
              obtainRequest(
                  target,
                  targetListener,
                  thumbnailOptions,
                  coordinator,
                  transitionOptions,
                  getThumbnailPriority(priority),
                  overrideWidth,
                  overrideHeight,
                  callbackExecutor);
    
          coordinator.setRequests(fullRequest, thumbnailRequest);
          return coordinator;
        } else {
          // 没有缩略图时,构造请求
          return obtainRequest(
              target,
              targetListener,
              requestOptions,
              parentCoordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              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);
      }
    }
    

    构建目标Request请求的代码比较长,如果我们配置了缩略图要求,它将构建缩略图请求,并和目标请求一起放入到协调器中。ThumbnailRequestCoordinator 请求协调器,可以用来协调各请求的顺序。

    我们只分析目标请求流程,也就是没有设置缩略图的情况。由obtain静态方法可以看到,最终获得的目标Request对象就是SingleRequest,它封装了图片请求需要的各个成员。

    public final class SingleRequest<R> implements Request,
        SizeReadyCallback,
        ResourceCallback,
        FactoryPools.Poolable {
        
        public static <R> SingleRequest<R> obtain(
          Context context,
          GlideContext glideContext,
          Object model,
          Class<R> transcodeClass,
          BaseRequestOptions<?> requestOptions,
          int overrideWidth,
          int overrideHeight,
          Priority priority,
          Target<R> target,
          RequestListener<R> targetListener,
          @Nullable List<RequestListener<R>> requestListeners,
          RequestCoordinator requestCoordinator,
          Engine engine,
          TransitionFactory<? super R> animationFactory,
          Executor callbackExecutor) {
        @SuppressWarnings("unchecked") SingleRequest<R> request =
            (SingleRequest<R>) POOL.acquire();
    
        //创建SingleRequest对象
        if (request == null) {
          request = new SingleRequest<>();
        }
        //初始化
        request.init(
            context,
            glideContext,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            targetListener,
            requestListeners,
            requestCoordinator,
            engine,
            animationFactory,
            callbackExecutor);
        return request;
      }
    
      //赋值成员变量
      private synchronized void init(
          Context context,
          GlideContext glideContext,
          Object model,
          Class<R> transcodeClass,
          BaseRequestOptions<?> requestOptions,
          int overrideWidth,
          int overrideHeight,
          Priority priority,
          Target<R> target,
          RequestListener<R> targetListener,
          @Nullable List<RequestListener<R>> requestListeners,
          RequestCoordinator requestCoordinator,
          Engine engine,
          TransitionFactory<? super R> animationFactory,
          Executor callbackExecutor) {
        this.context = context;
        this.glideContext = glideContext;
        this.model = model;
        this.transcodeClass = transcodeClass;
        this.requestOptions = requestOptions;
        this.overrideWidth = overrideWidth;
        this.overrideHeight = overrideHeight;
        this.priority = priority;
        this.target = target;
        this.targetListener = targetListener;
        this.requestListeners = requestListeners;
        this.requestCoordinator = requestCoordinator;
        this.engine = engine;
        this.animationFactory = animationFactory;
        this.callbackExecutor = callbackExecutor;
        status = Status.PENDING;
    
        if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
          requestOrigin = new RuntimeException("Glide request origin trace");
        }
      }
    
    }
    

    目标Request已经构建完成,再回到requestManager.track(target, request)这行代码,看Request如何被发出去的。它通过RequestManager来调用。

    public class RequestManager implements LifecycleListener,
        ModelTypes<RequestBuilder<Drawable>> {
      
        //请求追踪器
      private final RequestTracker requestTracker;
    
      public RequestManager(
          @NonNull Glide glide, @NonNull Lifecycle lifecycle,
          @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
        this(
            glide,
            lifecycle,
            treeNode,
            new RequestTracker(),//创建请求追踪器
            glide.getConnectivityMonitorFactory(),
            context);
      }
    
      synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
        targetTracker.track(target);
        // 开始请求
        requestTracker.runRequest(request);
      }
    
    
    }
    

    任务被移交给了RequestTracker请求追踪器进行追踪,这个对象RequestManager在构造时创建的。

    public class RequestTracker {
       private final Set<Request> requests =
          Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
      private final List<Request> pendingRequests = new ArrayList<>();
      private boolean isPaused;
    
      //执行请求任务
      public void runRequest(@NonNull Request request) {
        //添加到集合中
        requests.add(request);
        //没有暂停
        if (!isPaused) {
          //开始请求
          request.begin();
        } else {
        //被暂停则清理掉某些资源
          request.clear();
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Paused, delaying request");
          }
          //添加到待处理列表
          pendingRequests.add(request);
        }
    
      }
    

    如果任务此时被暂停了,那么将清理掉某些资源,但这个Request 还可以通过begin()方法来重新发出,所以被保存到pendingRequests待处理
    列表中。

    上面说过,所有图片请求相关的成员都被封装到Request(SingleRequest )对象中,它将指定Target去加载自己的资源。

    public final class SingleRequest<R> implements Request,
        SizeReadyCallback,
        ResourceCallback,
        FactoryPools.Poolable {
    
      public synchronized void begin() {
        assertNotCallingCallbacks();
        stateVerifier.throwIfRecycled();
        startTime = LogTime.getLogTime();
        //即地址为null
        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;
      // 如果指定了宽高,直接回调 onSizeReady
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          onSizeReady(overrideWidth, overrideHeight);
        } else {
        // 根据 target 的宽高来加载图片的宽高
          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));
        }
    
      }
      
    public synchronized void onSizeReady(int width, int height) {
        stateVerifier.throwIfRecycled();
        if (IS_VERBOSE_LOGGABLE) {
          logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
        }
        if (status != Status.WAITING_FOR_SIZE) {
          return;
        }
        status = Status.RUNNING;
    
        float sizeMultiplier = requestOptions.getSizeMultiplier();
        this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
        this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
    
        if (IS_VERBOSE_LOGGABLE) {
          logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
        }
    
        //加载图片并返回状态
        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);
        
        if (status != Status.RUNNING) {
          loadStatus = null;
        }
        if (IS_VERBOSE_LOGGABLE) {
          logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
        }
      }
    
    }
    

    加载分两种情况,如果指定了一个固定的宽高,就会直接执行onSizeReady()方法。如果没指定的话,调用target.getSize()方法。这个target.getSize()方法,它会根据ImageView布局设置的宽高,算出图片应该显示的宽高。计算完之后,它也会调用onSizeReady()方法。

    但请求加载流程还不是在这个类中执行的,它把这个任务交给了Engine对象来处理,这个对象是在GlideBuilder的build方法中创建的,我们前面分析过,在build方法中还创建了几个缓存池和以及复用池,这些池子都封装到了Engine对象中。并且在随后的Glide构造方法中构建GlideContext对象时,将其保存到这个上下文中。

    public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {
    
    
    
    
        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) {
    
    
        long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    
        // 创建资源索引 KEY
        EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
            resourceClass, transcodeClass, options);
    
        //从缓存中取
        EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
        if (active != null) {
          cb.onResourceReady(active, DataSource.MEMORY_CACHE);
          if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Loaded resource from active resources", startTime, key);
          }
          return null;
        }
        //从缓存中获取
        EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
        if (cached != null) {
          cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
          if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Loaded resource from cache", startTime, key);
          }
          return null;
        }
        // 获取已经存在的加载任务 ,onlyRetrieveFromCache 参数表示是否只加载缓存中的数据
        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
        if (current != null) {
          // 添加 SingleRequest 回调对象 
          current.addCallback(cb, callbackExecutor);
          if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Added to existing load", startTime, key);
          }
          return new LoadStatus(cb, current);
        }
    
        // 构造 EngineJob 对象,用于启动解码任务
        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);
        // 缓存加载任务
        jobs.put(key, engineJob);
        // 添加 SingleRequest 回调对象 
        engineJob.addCallback(cb, callbackExecutor);
        // 执行解码任务
        engineJob.start(decodeJob);
    
        if (VERBOSE_IS_LOGGABLE) {
          logWithTimeAndKey("Started new load", startTime, key);
        }
        return new LoadStatus(cb, engineJob);
      }
    
    }
    

    既然Engine 封装了许多缓存池,那么做网络请求前,必然先看缓存有没有。buildKey方法将几个参数封装成EngineKey ,根据这个Key 来获取内存缓存数据,如果存在,则直接回调成功,如果不存在,则新建EngineJob 对象和DecodeJob解码器,DecodeJob实现了Runnable,通过EngineJob 对象调用start来启动。

    缓存的获取这里先不分析,我们分析首次加载,即没有缓存的情况。那么,紧接着的工作又传递给了EngineJob 对象,它会通过线程池来开启DecodeJob这个Runnable。

    class EngineJob<R> implements DecodeJob.Callback<R>,
        Poolable {
    
        //通过线程池启动图片加载任务
      public synchronized void start(DecodeJob<R> decodeJob) {
        this.decodeJob = decodeJob;
        GlideExecutor executor = decodeJob.willDecodeFromCache()
            ? diskCacheExecutor
            : getActiveSourceExecutor();
        executor.execute(decodeJob);
      }
    
    }
    

    很显然,GlideExecutor 是Glide自定义的Executor,它内部实现了线程池。因此,我们直接看DecodeJob的run方法。

    class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
        Runnable,
        Comparable<DecodeJob<?>>,
        Poolable {
      //加载辅助类
      private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();
    
    
        DecodeJob<R> init(
          GlideContext glideContext,
          Object model,
          EngineKey loadKey,
          Key signature,
          int width,
          int height,
          Class<?> resourceClass,
          Class<R> transcodeClass,
          Priority priority,
          DiskCacheStrategy diskCacheStrategy,
          Map<Class<?>, Transformation<?>> transformations,
          boolean isTransformationRequired,
          boolean isScaleOnlyOrNoTransform,
          boolean onlyRetrieveFromCache,
          Options options,
          Callback<R> callback,
          int order) {
        decodeHelper.init(
            glideContext,
            model,
            signature,
            width,
            height,
            diskCacheStrategy,
            resourceClass,
            transcodeClass,
            priority,
            options,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            diskCacheProvider);
        this.glideContext = glideContext;
        this.signature = signature;
        this.priority = priority;
        this.loadKey = loadKey;
        this.width = width;
        this.height = height;
        this.diskCacheStrategy = diskCacheStrategy;
        this.onlyRetrieveFromCache = onlyRetrieveFromCache;
        this.options = options;
        this.callback = callback;
        this.order = order;
        this.runReason = RunReason.INITIALIZE;//初始化RunReason为INITIALIZE
        this.model = model;
        return this;
      }
    
       public void run() {
       
        GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
      
        DataFetcher<?> localFetcher = currentFetcher;
        try {
          if (isCancelled) {
            notifyFailed();
            return;
          }
          //进入runWrapped
          runWrapped();
        } catch (CallbackException e) {
           throw e;
        } catch (Throwable t) {
     
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "DecodeJob threw unexpectedly"
                + ", isCancelled: " + isCancelled
                + ", stage: " + stage, t);
          }
    
          if (stage != Stage.ENCODE) {
            throwables.add(t);
            notifyFailed();
          }
          if (!isCancelled) {
            throw t;
          }
          throw t;
        } finally {
          if (localFetcher != null) {
            localFetcher.cleanup();
          }
          GlideTrace.endSection();
        }
      }
    
       private void runWrapped() {
        switch (runReason) {
          case INITIALIZE:
            stage = getNextStage(Stage.INITIALIZE);
            currentGenerator = getNextGenerator();
            runGenerators();
            break;
          case SWITCH_TO_SOURCE_SERVICE:
            runGenerators();
            break;
          case DECODE_DATA:
            decodeFromRetrievedData();
            break;
          default:
            throw new IllegalStateException("Unrecognized run reason: " + runReason);
        }
      }
    
      //获取不同类型加载器
      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);
        }
      }
    
      //根据不同加载器获取图片
      private void runGenerators() {
        currentThread = Thread.currentThread();
        startFetchTime = LogTime.getLogTime();
        boolean isStarted = false;
        while (!isCancelled && currentGenerator != null
            && !(isStarted = currentGenerator.startNext())) {
          stage = getNextStage(stage);
          currentGenerator = getNextGenerator();
    
          if (stage == Stage.SOURCE) {
            reschedule();
            return;
          }
        }
       
        if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
          notifyFailed();
        }
    
      }
    }
    

    在DecodeJob被构造和初始化时,RunReason设置为INITIALIZE,也就是说,runWrapped进入了INITIALIZE这个case,如代码所示,有处理过的缓存资源加载器、原始图片资源缓存加载器和远程图片资源加载器3种不同类型的加载器,会根据当前的状态决定使用哪一个,由于是首次加载,因此,将获取到远程图片资源加载器,即SourceGenerator这个对象。

    runGenerators方法内是一个while递归循环,它通过加载器的startNext方法来执行加载的任务,开启成功结束循环,不再寻找新的加载器。

    class SourceGenerator implements DataFetcherGenerator,
        DataFetcher.DataCallback<Object>,
        DataFetcherGenerator.FetcherReadyCallback {
    
      private final DecodeHelper<?> helper;
    
      private volatile ModelLoader.LoadData<?> loadData;
    
      public boolean startNext() {
        //判断是否有缓存
        if (dataToCache != null) {
          Object data = dataToCache;
          dataToCache = null;
          // 缓存数据
          cacheData(data);
        }
    
        if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
          return true;
        }
        sourceCacheGenerator = null;
    
        // 没有缓存,从远程加载
        loadData = null;
        boolean started = false;
         // 遍历所有的ModelLoader模块加载器
        while (!started && hasNextModelLoader()) {
          //拿到 HttpGlideUrlLoader 对象
          loadData = helper.getLoadData().get(loadDataListIndex++);
          if (loadData != null
              && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
            started = true;
            // 调用 HttpUrlFetcher 的 loadData 方法
            loadData.fetcher.loadData(helper.getPriority(), this);
          }
        }
        return started;
      }
    
    }
    

    DecodeHelper是在Engine中构建的,使用getLoadData获取到ModelLoader的列表。

    final class DecodeHelper<Transcode> {
    
        //获取List<LoadData<?>>
       List<LoadData<?>> getLoadData() {
        if (!isLoadDataSet) {
          isLoadDataSet = true;
          loadData.clear();
          List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
          
          for (int i = 0, size = modelLoaders.size(); i < size; i++) {
            //这个ModelLoader为HttpGlideUrlLoader
            ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
            //构建LoadData
            LoadData<?> current =
                modelLoader.buildLoadData(model, width, height, options);
            if (current != null) {
              loadData.add(current);
            }
          }
        }
        return loadData;
      }
    }
    
    

    这里获取到ModelLoader为HttpGlideUrlLoader类型的,通过buildLoadData构建一个ModelLoader.LoadData对象。

    public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
    
    
       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);
        //构建HttpUrlFetcher将它传递给LoadData
        return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
       }
    }
    

    因此,上面loadData.fetcher.loadData代码就是在HttpUrlFetcher中执行的。

    public class HttpUrlFetcher implements DataFetcher<InputStream> {
        
      @Override
      public void loadData(@NonNull Priority priority,
          @NonNull DataCallback<? super InputStream> callback) {
        long startTime = LogTime.getLogTime();
    
        // 调用 loadDataWithRedirects 方法执行网络请求
        try {
          InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
          //将输入流回调给DataCallback
          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));
          }
        }
      }
    
      //执行网络请求
      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) {
            
          }
        }
        //根据url构建Connection 
        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();
        //状态码为200,将输入流返回
        if (isHttpOk(statusCode)) {
          return getStreamForSuccessfulRequest(urlConnection);
        } else if (isHttpRedirect(statusCode)) {
          String redirectUrlString = urlConnection.getHeaderField("Location");
          if (TextUtils.isEmpty(redirectUrlString)) {
            throw new HttpException("Received empty or null redirect url");
          }
          URL redirectUrl = new URL(url, redirectUrlString);
          
          cleanup();
          return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
        } else if (statusCode == INVALID_STATUS_CODE) {
          throw new HttpException(statusCode);
        } else {
          throw new HttpException(urlConnection.getResponseMessage(), statusCode);
        }
      }
    
      //获取输入流
       private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
          throws IOException {
        if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
          int contentLength = urlConnection.getContentLength();
          stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
        } else {
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
          }
          stream = urlConnection.getInputStream();
        }
        return stream;
      }
    
      //状态码为200
      private static boolean isHttpOk(int statusCode) {
        return statusCode / 100 == 2;
      }
    }
    

    分析到这,总算看到网络请求的调用了。如果状态为200,那么将获取得数据输入流,回调给DataCallback接口,它是从loadData方法传递进来的,再回头loadData的调用知道,它其实就是SourceGenerator对象。

    
    class SourceGenerator implements DataFetcherGenerator,
        DataFetcher.DataCallback<Object>,
        DataFetcherGenerator.FetcherReadyCallback {
    
       private final FetcherReadyCallback cb;
       private final DecodeHelper<?> helper;
        //缓存流
        private Object dataToCache;
      SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
        this.helper = helper;
        this.cb = cb;
      }
    
        @Override
      public void onDataReady(Object data) {
        DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
        //如果设置了磁盘缓存
        if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
          //将数据流缓存到磁盘对象中
          dataToCache = data;
          // 重启 DecodeJob 任务
           cb.reschedule();
        } else {
          //没有缓存,回调给DecodeJob
          cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
              loadData.fetcher.getDataSource(), originalKey);
        }
      }
    
    }
    

    Glide认为远程网络图片获取是昂贵的,所以默认情况下网络图片会缓存原图,但本地图片,包括drawable/assets等不会缓存原图。

    有没有缓存,最终都会调用到onDataFetcherReady这个方法。与没有缓存相比,有缓存流程上的区别是,会将数据流缓存到磁盘中,然后开一个新的线程,再通过另一个缓存加载器处理,并获取数据流。以上说过,默认是有缓存原图的,因此,我们先分析缓存的调用流程。

    在这里提一下,整个流程的调用就类似一个命令下发,这个命令会一层层往下传递,传给到最后一棒的对象去取得数据,再沿着原来的路线,将完成的数据,一层层往回传。这一点务必记住,后面的流程都是在一边处理数据,一边向之前的对象传递,直至传给SingleRequest这个对象里的Target成员,来显示图片。

    因此,这里就开始了往前的传递,调用reschedule的对象为DecodeJob。

    class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
        Runnable,
        Comparable<DecodeJob<?>>,
        Poolable {
    
     @Override
      public void reschedule() {
        //RunReason被置为SWITCH_TO_SOURCE_SERVICE
        runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
        //回调给EngineJob
        callback.reschedule(this);
      }
    

    RunReason被置为SWITCH_TO_SOURCE_SERVICE。紧接着再次往回通知EngineJob对象。

    class EngineJob<R> implements DecodeJob.Callback<R>,
        Poolable {
    
      @Override
      public void reschedule(DecodeJob<?> job) {
            getActiveSourceExecutor().execute(job);
      }
    }
    

    重新开启线程,执行DecodeJob这个任务。这回直接执行runGenerators方法,再次调用SourceGenerator的startNext方法,此时缓存就不为null了。

    class SourceGenerator implements DataFetcherGenerator,
        DataFetcher.DataCallback<Object>,
        DataFetcherGenerator.FetcherReadyCallback {
      //缓存流
      private Object dataToCache;
      //缓存加载器
      private DataCacheGenerator sourceCacheGenerator;
    
      @Override
      public boolean startNext() {
        //缓存不为null
        if (dataToCache != null) {
          Object data = dataToCache;
          dataToCache = null;
          cacheData(data);
        }
      //此时sourceCacheGenerator 不为null
      if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
          return true;
        }
       ......
      }
    
      private void cacheData(Object dataToCache) {
        long startTime = LogTime.getLogTime();
        try {
          Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
          DataCacheWriter<Object> writer =
              new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
          originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
          helper.getDiskCache().put(originalKey, writer);
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Finished encoding source to cache"
                + ", key: " + originalKey
                + ", data: " + dataToCache
                + ", encoder: " + encoder
                + ", duration: " + LogTime.getElapsedMillis(startTime));
          }
        } finally {
          loadData.fetcher.cleanup();
        }
    
        //构建缓存加载器来处理
        sourceCacheGenerator =
            new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
      }
    

    dataToCache 将不再是 null ,所以会将数据缓存到本地硬盘,并启动另一个加载器DataCacheGenerator,这个加载器正是用来加载缓存在本地的图片的。它赋值给了成员变量sourceCacheGenerator ,随后执行其startNext方法。

    DataCacheGenerator和ResourceCacheGenerator这两个加载器跟SourceGenerator类似,只不过根据不同情形的图片进行加载:

    • DataCacheGenerator:用于加载原始图片。
    • ResourceCacheGenerator:用于加载处理过的图片。
    • SourceGenerator:用于加载网络图片。

    因此,数据从缓存中加载成功,同样回传给DataCacheGenerator的 onDataReady方法。

    class DataCacheGenerator implements DataFetcherGenerator,
        DataFetcher.DataCallback<Object> {
    
       public void onDataReady(Object data) {
        cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
      }
    }
    

    前面我们提到过,有没有缓存,最终都会调用DecodeJob的onDataFetcherReady方法,因为它是用来解码的。

    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;
        this.currentData = data;
        this.currentFetcher = fetcher;
        this.currentDataSource = dataSource;
        this.currentAttemptingKey = attemptedKey;
        
        if (Thread.currentThread() != currentThread) {
          runReason = RunReason.DECODE_DATA;
          callback.reschedule(this);
        } else {
          GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
          try {
            //解码数据
            decodeFromRetrievedData();
          } finally {
            GlideTrace.endSection();
          }
        }
    
      //解码获取Resource
       private void decodeFromRetrievedData() {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Retrieved data", startFetchTime,
              "data: " + currentData
                  + ", cache key: " + currentSourceKey
                  + ", fetcher: " + currentFetcher);
        }
        Resource<R> resource = null;
        try {
          //解码得到LazyBitmapDrawableResource
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
        } catch (GlideException e) {
          e.setLoggingDetails(currentAttemptingKey, currentDataSource);
          throwables.add(e);
        }
    
        //进行编码输出
        if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
    
      private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
          DataSource dataSource) throws GlideException {
        try {
          if (data == null) {
            return null;
          }
          long startTime = LogTime.getLogTime();
          //从DecodeHelper中获取LoadPath对象
          Resource<R> result = decodeFromFetcher(data, dataSource);
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Decoded result " + result, startTime);
          }
          return result;
        } finally {
          fetcher.cleanup();
        }
      }
    
      private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
          throws GlideException {
        LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
        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);
        DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
        try {
          //使用LoadPath进行解码
          return path.load(
              rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
        } finally {
          rewinder.cleanup();
        }
      }
    }
    

    解码的流程最终是通过LoadPath这个对象来进行处理的。它是根据传入的处理数据,来返回特定的数据解码处理器对象。

    public class LoadPath<Data, ResourceType, Transcode> {
      
    
      public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
          int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
        List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
        try {
          return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
        } finally {
          listPool.release(throwables);
        }
      }
    
     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;
        //遍历从列表获取DecodePath进行解码
        for (int i = 0, size = decodePaths.size(); i < size; i++) {
          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类还并不是最终的解码器,它只是封装解码和转码的工具,它本身不做解码转码的具体操作。

    public class DecodePath<DataType, ResourceType, Transcode> {
      //转码器
      private final ResourceTranscoder<ResourceType, Transcode> transcoder;
    
      public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
          @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
         // 返回的可能是 BitmapResource 对象,看具体类型
        Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    
        // 回调 DecodeJob 的 onResourceDecoded 方法,返回需要转码的类型
        Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    
        //转码 BitmapResource,返回 LazyBitmapDrawableResource
        return transcoder.transcode(transformed, options);
      }
    
      private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
          int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
    
        Resource<ResourceType> result = null;
    
       //遍历获取StreamBitmapDecoder
        for (int i = 0, size = decoders.size(); i < size; i++) {
          ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
          try {
            DataType data = rewinder.rewindAndGet();
            if (decoder.handles(data, options)) {
              data = rewinder.rewindAndGet();
              //解码成Drawable 
              result = decoder.decode(data, width, height, options);
            }
           
          } 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;
      }
    
    }
    
    

    这里需要的是 Drawable 类型,所以,decodeResource方法最终会通过 StreamBitmapDecoder将数据流解码成一个 BitmapResource 对象。再通过ResourceTranscoder转码器,它是BitmapDrawableTranscoder类型的,转码为LazyBitmapDrawableResource对象。

    public class BitmapDrawableTranscoder implements ResourceTranscoder<Bitmap, BitmapDrawable> {
      private final Resources resources;
    
      @SuppressWarnings("unused")
      public BitmapDrawableTranscoder(@NonNull Context context) {
        this(context.getResources());
      }
     
      @Deprecated
      public BitmapDrawableTranscoder(
          @NonNull Resources resources, @SuppressWarnings("unused") BitmapPool bitmapPool) {
        this(resources);
      }
    
      public BitmapDrawableTranscoder(@NonNull Resources resources) {
        this.resources = Preconditions.checkNotNull(resources);
      }
    
      //转码
      @Override
      public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
          @NonNull Options options) {
        return LazyBitmapDrawableResource.obtain(resources, toTranscode);
      }
    }
    
    public final class LazyBitmapDrawableResource implements Resource<BitmapDrawable>,
        Initializable {
    
      //获取LazyBitmapDrawableResource对象
      public static Resource<BitmapDrawable> obtain(
          @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
        if (bitmapResource == null) {
          return null;
        }
        return new LazyBitmapDrawableResource(resources, bitmapResource);
    
      }
    
      //获取BitmapDrawable
      @Override
      public BitmapDrawable get() {
        return new BitmapDrawable(resources, bitmapResource.get());
      }
    
    }
    

    这里注意到get方法返回了BitmapDrawable对象,它就是最终用来显示到ImageView上的类型。现在解码和转码工作已经完成了。所以,数据继续往回传递通知上层,将获取到的结果进行展示。

    因此,回到DecodeJob类的decodeFromRetrievedData方法内部,调用notifyEncodeAndRelease 继续往下执行。

    class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
        Runnable,
        Comparable<DecodeJob<?>>,
        Poolable {
    
      private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
        if (resource instanceof Initializable) {
          ((Initializable) resource).initialize();
        }
        //将资源锁定
        Resource<R> result = resource;
        LockedResource<R> lockedResource = null;
        if (deferredEncodeManager.hasResourceToEncode()) {
          lockedResource = LockedResource.obtain(resource);
          result = lockedResource;
        }
        //通知上层任务完成
        notifyComplete(result, dataSource);
    
        stage = Stage.ENCODE;
        try {
          if (deferredEncodeManager.hasResourceToEncode()) {
            deferredEncodeManager.encode(diskCacheProvider, options);
          }
        } finally {
          if (lockedResource != null) {
            lockedResource.unlock();
          }
        }
     
        onEncodeComplete();
      }
    
      private void notifyComplete(Resource<R> resource, DataSource dataSource) {
        setNotifiedOrThrow();
        //回调给EngineJob
        callback.onResourceReady(resource, dataSource);
      }
    
    }
    

    LazyBitmapDrawableResource数据继续往回传给EngineJob类。它还会继续往上传给SingleRequest类。

    class EngineJob<R> implements DecodeJob.Callback<R>,
        Poolable {
    //这是LazyBitmapDrawableResource
     private Resource<?> resource;
    
      @Override
      public void onResourceReady(Resource<R> resource, DataSource dataSource) {
        //保存数据
        synchronized (this) {
          this.resource = resource;
          this.dataSource = dataSource;
        }
        notifyCallbacksOfResult();
      }
    
      @Synthetic
      void notifyCallbacksOfResult() {
    
        ResourceCallbacksAndExecutors copy;
        Key localKey;
        EngineResource<?> localResource;
        synchronized (this) {
          stateVerifier.throwIfRecycled();
          if (isCancelled) {
            resource.recycle();
            release();
            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;
          copy = cbs.copy();
          incrementPendingCallbacks(copy.size() + 1);
          localKey = key;
          localResource = engineResource;
        }
    
        listener.onEngineJobComplete(this, localKey, localResource);
        //通过子线程回调
        for (final ResourceCallbackAndExecutor entry : copy) {
          entry.executor.execute(new CallResourceReady(entry.cb));
        }
        decrementPendingCallbacks();
      }
    
    
       private class CallResourceReady implements Runnable {
    
        private final ResourceCallback cb;
    
        CallResourceReady(ResourceCallback cb) {
          this.cb = cb;
        }
    
        @Override
        public void run() {
          synchronized (EngineJob.this) {
            if (cbs.contains(cb)) {
           
              engineResource.acquire();
              //调用callCallbackOnResourceReady传递给SingleRequest
              callCallbackOnResourceReady(cb);
              removeCallback(cb);
            }
            decrementPendingCallbacks();
          }
        }
      }
    
      @SuppressWarnings("WeakerAccess")
      @Synthetic
      synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
        try {
          //调用SingleRequest的onResourceReady方法
          cb.onResourceReady(engineResource, dataSource);
        } catch (Throwable t) {
          throw new CallbackException(t);
        }
      }
    
    }
    

    EngineJob构建了一个EngineResource,将LazyBitmapDrawableResource封装在它的内部,然后开启线程,将数据传递给了SingleRequest类。

    public final class SingleRequest<R> implements Request,
        SizeReadyCallback,
        ResourceCallback,
        FactoryPools.Poolable {
      
         @Override
      public synchronized 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;
        }
        从EngineResource中获取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;
        }
    
        if (!canSetResource()) {
          releaseResource(resource);
          status = Status.COMPLETE;
          return;
        }
      //通知Target显示图片
        onResourceReady((Resource<R>) resource, (R) received, dataSource);
      }
    
    private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
        
        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;
          if (requestListeners != null) {
            for (RequestListener<R> listener : requestListeners) {
              anyListenerHandledUpdatingTarget |=
                  listener.onResourceReady(result, model, target, dataSource, isFirstResource);
            }
          }
          anyListenerHandledUpdatingTarget |=
              targetListener != null
                  && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
    
          if (!anyListenerHandledUpdatingTarget) {
            Transition<? super R> animation =
                animationFactory.build(dataSource, isFirstResource);
            //显示资源
            target.onResourceReady(result, animation);
          }
        } finally {
          isCallingCallbacks = false;
        }
    
        notifyLoadSuccess();
      }
    }
    

    注意代码中的resource.get()调用,这个resource是传递过来的EngineResource,上面说过,它已经持有了LazyBitmapDrawableResource,这个get方法,便会调用LazyBitmapDrawableResource的get方法获取到BitmapDrawable对象,紧接着调用onResourceReady方法让Target去展示图片。

    在最前面分析说过,这个Target是ImageViewTarget的子类,BitmapImageViewTarget。

    public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
        implements Transition.ViewAdapter {
      
       @Override
      public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
        if (transition == null || !transition.transition(resource, this)) {
          //设置资源
          setResourceInternal(resource);
        } else {
          maybeUpdateAnimatable(resource);
        }
      }
    
        private void setResourceInternal(@Nullable Z resource) {
        //调用子类方法
        setResource(resource);
        maybeUpdateAnimatable(resource);
      }
      
       protected abstract void setResource(@Nullable Z resource);
    }
    
    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);
      }
    }
    

    到此,Glide整个图片加载流程分析完毕。其中的into流程是最复杂的,因为Glide做了大量的缓存处理和对象复用。但整个基本调用流程是:下发一个Request后,通过网络请求获得数据,进行解码和转码,再沿路返回到Request类中,让Target去做图片展示。

    相关文章

      网友评论

          本文标题:Glide源码(二)

          本文链接:https://www.haomeiwen.com/subject/hcavactx.html