Glide加载流程源码分析

作者: h2coder | 来源:发表于2022-04-12 00:03 被阅读0次

    前言

    Glide是Android开发中,非常热门的一款图片加载框架,本篇来分析一下Glide的源码。

    简单使用

    Glide加载一个Http的Url图片,总共分3步,with(),load(),into(),源码分析也是从这3个API口子开始进行。

    • with(),通过context获取Glide实例,并且创建RequestManager,并且绑定context生命周期,例如context为Activity时,在onStop中暂停请求,onStart中恢复请求。
    • load(),通过一个url,获取RequestBuilder实例,并且把url保存起来。
    • into(),开始加载url,并把获取到的图片加载到传入的ImageView中。
    Glide.with(context).load(url).into(imageView);
    

    源码分析

    Glide.with(context)

    @NonNull
    public static RequestManager with(@NonNull Context context) {
        return getRetriever(context).get(context);
    }
    
    @NonNull
    private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        // Context could be null for other reasons (ie the user passes in null), but in practice it will
        // only occur due to errors with the Fragment lifecycle.
        //判空
        Preconditions.checkNotNull(
            context,
            "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
                + "returns null (which usually occurs when getActivity() is called before the Fragment "
                + "is attached or after the Fragment is destroyed).");
        //Glide.get(context),或者Glide单实例
        return Glide.get(context).getRequestManagerRetriever();
        }
    
        @NonNull
        public static Glide get(@NonNull Context context) {
        //双重double check实现单例
        if (glide == null) {
          synchronized (Glide.class) {
            if (glide == null) {
              //构造Glide实例
              checkAndInitializeGlide(context);
            }
          }
        }
    
        return glide;
    }
    
    • Glide.with(context),通过Context,获取Glide单实例,再获取RequestManagerRetriever对象
    • RequestManagerRetriever.get(context),获取RequestManager实例

    Glide单例

    Glide单例使用Double Check,双重检查来实现单例,最终会调用到build()方法,进行构建Glide实例,并初始化一些系列对象,例如GlideModuleRequestManagerRetrieverEngine

    @NonNull
    public static Glide get(@NonNull Context context) {
        //双重double check实现单例
        if (glide == null) {
          synchronized (Glide.class) {
            if (glide == null) {
              //构造Glide实例
              checkAndInitializeGlide(context);
            }
          }
        }
        
        return glide;
    }
    
    private static void checkAndInitializeGlide(@NonNull Context context) {
        // In the thread running initGlide(), one or more classes may call Glide.get(context).
        // Without this check, those calls could trigger infinite recursion.
        if (isInitializing) {
          throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
        }
        isInitializing = true;
        //构造Glide实例
        initializeGlide(context);
        isInitializing = false;
    }
    
    /**
    * 构造Glide实例
    */
    private static void initializeGlide(@NonNull Context context) {
        initializeGlide(context, new GlideBuilder());
    }
    
    /**
    * 构造Glide实例
    *
    * @param builder Glide配置
    */
    @SuppressWarnings("deprecation")
    private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
        Context applicationContext = context.getApplicationContext();
        //反射创建 com.bumptech.glide.GeneratedAppGlideModuleImpl,如果能找到,就说明自定义了GlideModule
        GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
        List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
        if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
          //找不到,但开启了isManifestParsingEnabled,就读取AndroidManifest.xml上配置的GlideModule
          manifestModules = new ManifestParser(applicationContext).parse();
        }
        //根据配置的GlideModule过滤名单,剔除名单上配置的GlideModule
        if (annotationGeneratedModule != null
            && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
          Set<Class<?>> excludedModuleClasses =
              annotationGeneratedModule.getExcludedModuleClasses();
          Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
          while (iterator.hasNext()) {
            com.bumptech.glide.module.GlideModule current = iterator.next();
            if (!excludedModuleClasses.contains(current.getClass())) {
              continue;
            }
            if (Log.isLoggable(TAG, Log.DEBUG)) {
              Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
            }
            iterator.remove();
          }
        }
        
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
            Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
          }
        }
        
        //获取RequestManager工厂,用于在with()方法中,创建RequestManager
        RequestManagerRetriever.RequestManagerFactory factory =
            annotationGeneratedModule != null
                ? annotationGeneratedModule.getRequestManagerFactory() : null;
        builder.setRequestManagerFactory(factory);
        //遍历调用AndroidManifest.xml中配置的GlideModule上配置的applyOptions()方法
        for (com.bumptech.glide.module.GlideModule module : manifestModules) {
          module.applyOptions(applicationContext, builder);
        }
        //遍历调用注解配置的GlideModule上配置的applyOptions()方法
        if (annotationGeneratedModule != null) {
          annotationGeneratedModule.applyOptions(applicationContext, builder);
        }
        //构建Glide实例
        Glide glide = builder.build(applicationContext);
        //调用AndroidManifest.xml中配置的GlideModule中的registerComponents()方法
        for (com.bumptech.glide.module.GlideModule module : manifestModules) {
          module.registerComponents(applicationContext, glide, glide.registry);
        }
        //调用注解配置的GlideModule中的registerComponents()方法
        if (annotationGeneratedModule != null) {
          annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
        }
        //Glide实现了ComponentCallbacks接口,用于被通知onConfigurationChanged()配置改变和onLowMemory()低内存通知
        applicationContext.registerComponentCallbacks(glide);
        //单例变量赋值
        Glide.glide = glide;
    }
    
    /**
    * Glide的构造
    */
    @NonNull
    Glide build(@NonNull Context context) {
        //源执行器,允许在其线程上进行网络操作,获取资源
        if (sourceExecutor == null) {
          sourceExecutor = GlideExecutor.newSourceExecutor();
        }
        
        //磁盘缓存执行器,不允许对其线程进行网络操作
        if (diskCacheExecutor == null) {
          diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
        }
        
        //动画执行器,不允许在其线程上进行网络操作
        if (animationExecutor == null) {
          animationExecutor = GlideExecutor.newAnimationExecutor();
        }
        
        //根据设备的参数计算需要设置的缓存大小
        if (memorySizeCalculator == null) {
          memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
        }
        
        //网络连接监听工厂
        if (connectivityMonitorFactory == null) {
          connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
        }
        
        //Bitmap缓存池,用于图片的缓存,使用LRUCache
        if (bitmapPool == null) {
          int size = memorySizeCalculator.getBitmapPoolSize();
          if (size > 0) {
            //LRUCache缓存
            bitmapPool = new LruBitmapPool(size);
          } else {
            //不使用缓存
            bitmapPool = new BitmapPoolAdapter();
          }
        }
        
        //一个固定大小的数组池,使用LRU策略,让池保持在最大字节下
        if (arrayPool == null) {
          arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
        }
        
        //图片内存缓存
        if (memoryCache == null) {
          memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
        }
        
        //磁盘缓存
        if (diskCacheFactory == null) {
          diskCacheFactory = new InternalCacheDiskCacheFactory(context);
        }
        
        //创建Engine,用于发起Request网络请求,读取磁盘图片
        if (engine == null) {
          engine =
              new Engine(
                  memoryCache,
                  diskCacheFactory,
                  diskCacheExecutor,
                  sourceExecutor,
                  GlideExecutor.newUnlimitedSourceExecutor(),
                  GlideExecutor.newAnimationExecutor(),
                  isActiveResourceRetentionAllowed);
        }
        
        //创建RequestManagerRetriever对象,getRetriever()方法返回该实例
        RequestManagerRetriever requestManagerRetriever =
            new RequestManagerRetriever(requestManagerFactory);
        
        //构造Glide
        return new Glide(
            context,
            engine,
            memoryCache,
            bitmapPool,
            arrayPool,
            requestManagerRetriever,
            connectivityMonitorFactory,
            logLevel,
            defaultRequestOptions.lock(),
            defaultTransitionOptions);
    }
    

    RequestManager 请求管理器

    RequestManager.get(context),通过Context,获取RequestManager实例,判断Context的类型,判空,当前为主线程,并且不是Application,判断是FragmentActivity、还是Activity、如果是ContextWrapper,则获取getBaseContext()递归再获取一遍。

    @NonNull
    public RequestManager get(@NonNull Context context) {
        if (context == null) {
          throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) {
          //找宿主Activity来创建RequestManager
          if (context instanceof FragmentActivity) {
            return get((FragmentActivity) context);
          } else if (context instanceof Activity) {
            return get((Activity) context);
          } else if (context instanceof ContextWrapper) {
            return get(((ContextWrapper) context).getBaseContext());
          }
        }
        //通过ApplicationContext,获取RequestManager
        return getApplicationManager(context);
    }
    

    以Context为FragmentActivity为例,看看做了些什么。

    @NonNull
    public RequestManager get(@NonNull FragmentActivity activity) {
        //如果不是主线程调用,使用ApplicationContext
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          //主线程,检查Activity是否销毁
          assertNotDestroyed(activity);
          //获取Fragment管理器
          FragmentManager fm = activity.getSupportFragmentManager();
          //通过插入SupportFragment来获取RequestManager
          //RequestManager被Glide用于开始、停止、管理Glide的请求
          return supportFragmentGet(
              activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
        }
    }
    
    /**
    * 通过插入SupportFragment来获取RequestManager
    */
    @NonNull
    private RequestManager supportFragmentGet(
          @NonNull Context context,
          @NonNull FragmentManager fm,
          @Nullable Fragment parentHint,
          boolean isParentVisible) {
        //获取Fragment实例
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        //从Fragment上,获取RequestManager实例
        RequestManager requestManager = current.getRequestManager();
        //Fragment上没有,则通过工厂进行创建
        if (requestManager == null) {
          // TODO(b/27524013): Factor out this Glide.get() call.
          Glide glide = Glide.get(context);
          requestManager =
              factory.build(
                  glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
          //让Fragment持有RequestManager实例,下次就不需要再创建了
          current.setRequestManager(requestManager);
        }
        return requestManager;
    }
    
    /**
    * 添加插入一个空的Fragment到Activity或Fragment上
    */
    @NonNull
    private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        //通过Tag查找
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        //没有添加过
        if (current == null) {
          //从缓存map中查找,找到则直接返回
          current = pendingSupportRequestManagerFragments.get(fm);
          //也找不到,则创建一个
          if (current == null) {
            current = new SupportRequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            //如果当前页面已经是可见的,那么马上调用lifecycle的onStart()
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            //加进缓存map,由于快速滚动会频繁触发,并且Fragment的事务是异步的,如果没有这个缓存map,可能会插入多个Fragment
            pendingSupportRequestManagerFragments.put(fm, current);
            //添加Fragment
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            //发消息到主线程,由于Fragment的事务也是通过Handler来进行异步的
            //所以这个消息如果被执行,那Fragment的事务肯定已经处理完了,那么就可以从map上移除Fragment实例了
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
    }
    
    • 获取FragmentActivity的FragmentManager,通过Tag查找SupportRequestManagerFragment实例,如果没有获取到,去pendingSupportRequestManagerFragments这个Map中获取
    • 如果能获取到,则取出Fragment绑定的RequestManager实例
    • 如果还是没有获取到,则创建这个Fragment实例,并把RequestManager通过setRequestManager(),把它们绑定起来
    • SupportRequestManagerFragment,其实是一个没有布局的Fragment,通过它来获取Activity的生命周期回调

    RequestManager.load(url)

    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable String string) {
        //asDrawable(),创建一个RequestBuilder,并且指定它的泛型为Drawable类型
        //调用RequestBuilder的load()方法,传入url
        return asDrawable().load(string);
    }
    
    @NonNull
    @CheckResult
    public RequestBuilder<Drawable> asDrawable() {
        return as(Drawable.class);
    }
    
    @CheckResult
    public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
        return new RequestBuilder<>(glide, this, resourceClass, context);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
        return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
    }
    
    @NonNull
    private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
        //保存了加载的资源
        this.model = model;
        //设置标志位,加载的时候会用到,如果没有设置为true,则直接执行错误回调
        isModelSet = true;
        return this;
    }
    
    • load()方法做的事情非常少,首先创建了一个RequestBuilder实例,并且指定它的泛型为Drawable,然后把传入的url,保存起来,并且设置了一个isModelSet标志位为true,就返回出去了

    RequestBuilder.into(imageView)

    @NonNull
    public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
        //检查是否是主线程,如不是,则抛异常
        Util.assertMainThread();
        //判空
        Preconditions.checkNotNull(view);
        
        RequestOptions requestOptions = this.requestOptions;
        if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
          // Clone in this method so that if we use this RequestBuilder to load into a View and then
          // into a different target, we don't retain the transformation applied based on the previous
          // View's scale type.
          //根据ImageView设置的ScaleType,添加对应的RequestOption
          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:
              // Do nothing.
          }
        }
        //transcodeClass是前面load()保存的资源类型
        return into(
            //构建ViewTarget,例如 DrawableImageViewTarget
            glideContext.buildImageViewTarget(view, transcodeClass),
            /*targetListener=*/ null,
            requestOptions);
    }
    
    /**
    * 根据要加载的资源的类型,构建ViewTarget
    */
    @NonNull
    public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
        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,通过setImageBitmap(),设置给ImageView
        if (Bitmap.class.equals(clazz)) {
          return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
        } else if (Drawable.class.isAssignableFrom(clazz)) {
          //加载成Drawable,通过setImageDrawable(),设置给ImageView
          //例如传入url,Glide.with(context).load(url).into(view),会通过asDrawable(),clazz就为Drawable.class
          return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
        } else {
          throw new IllegalArgumentException(
              "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
        }
      }
    }
    
    • 获取ImageView的ScaleType,就是缩放类型,如果有添加,则设置对应的类型到RequestOptions
    • 随后调用重载的into()方法
      • 调用buildImageViewTarget(),创建ViewTarget,并根据加载类型transcodeClass,创建BitmapImageViewTarget还是DrawableImageViewTarget,例如字符串Url,创建的类型为DrawableImageViewTarget
      • RequestListener,targetListener,请求监听,包含加载成功和加载失败2个回调,这里传的是null
      • RequestOptions,请求配置项

    into(target, reqeuestListener, options)

    private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
        //必须主线程
        Util.assertMainThread();
        //非空判断
        Preconditions.checkNotNull(target);
        //在RequestBuilder的load()方法中,会设置该标志位为true
        if (!isModelSet) {
          throw new IllegalArgumentException("You must call #load() before calling #into()");
        }
        
        options = options.autoClone();
        
        //创建请求,用于显示图片,可能来自内存缓存、磁盘缓存或网络中
        //返回的Request接口实现是SingleRequest
        Request request = buildRequest(target, targetListener, options);
        
        //拿出之前的请求做对比,如果能够复用,则复用之前的请求
        Request previous = target.getRequest();
        //2个请求的配置一致,那么可以考虑复用
        if (request.isEquivalentTo(previous)
                //设置了忽略缓存或previous还没有完成
            && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
          request.recycle();
          // If the request is completed, beginning again will ensure the result is re-delivered,
          // triggering RequestListeners and Targets. If the request is failed, beginning again will
          // restart the request, giving it another chance to complete. If the request is already
          // running, we can let it continue running without interruption.
          //没有运行,那么开始
          if (!Preconditions.checkNotNull(previous).isRunning()) {
            // Use the previous request rather than the new one to allow for optimizations like skipping
            // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
            // that are done in the individual Request.
            //开始请求
            previous.begin();
          }
          return target;
        }
        
        //不能复用之前的请求previous,那么就清除掉target上保存的request
        requestManager.clear(target);
        //重新设置新的request,并且设置到ImageView的tag上
        target.setRequest(request);
        //开始请求
        requestManager.track(target, request);
        
        return target;
    }
    
    • 通过buildRequest(),创建一个Request请求对象
    • 通过传入的Target对象,获取已存在的请求Reqeust对象
    • 判断是否可以复用已存在的请求
      • request和previous是否参数、请求类型都一致
      • 是否设置了跳过缓存,并且previous已完成
    • 如果不能复用,那么久构建新的Request对象,并通过RequestManager.track(target, request)开始请求

    buildRequest

      private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      RequestOptions requestOptions) {
        return buildRequestRecursive(
            target,
            targetListener,
            /*parentCoordinator=*/ null,
            transitionOptions,
            requestOptions.getPriority(),
            requestOptions.getOverrideWidth(),
            requestOptions.getOverrideHeight(),
            requestOptions);
    }
    
    private Request buildRequestRecursive(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
    
        // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
        //是否设置了错误时要显示的图片
        ErrorRequestCoordinator errorRequestCoordinator = null;
        if (errorBuilder != null) {
          errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
          parentCoordinator = errorRequestCoordinator;
        }
        
        //创建略缩图和原图的Request
        Request mainRequest =
            buildThumbnailRequestRecursive(
                target,
                targetListener,
                parentCoordinator,
                transitionOptions,
                priority,
                overrideWidth,
                overrideHeight,
                requestOptions);
        
        if (errorRequestCoordinator == null) {
          return mainRequest;
        }
        
        int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
        int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
        if (Util.isValidDimensions(overrideWidth, overrideHeight)
            && !errorBuilder.requestOptions.isValidOverride()) {
          errorOverrideWidth = requestOptions.getOverrideWidth();
          errorOverrideHeight = requestOptions.getOverrideHeight();
        }
        
        //错误时要显示的图片的Request
        Request errorRequest = errorBuilder.buildRequestRecursive(
            target,
            targetListener,
            errorRequestCoordinator,
            errorBuilder.transitionOptions,
            errorBuilder.requestOptions.getPriority(),
            errorOverrideWidth,
            errorOverrideHeight,
            errorBuilder.requestOptions);
        //把2个请求组合到ErrorRequestCoordinator
        errorRequestCoordinator.setRequests(mainRequest, errorRequest);
        return errorRequestCoordinator;
    }
    
    • 判断errorBuilder是否为空,这个errorBuilder是通过RequestBuilder.error()进行设置的,如果不为空,则将生成一个协调器ErrorRequestCoordinator,用于和下面的mainRequesterrorRequest进行协调,默认没有设置
    • buildThumbnailRequestRecursive(),生成mainRequest
    • 如果errorRequestCoordinator为空,则直接返回mainRequest
    • 如果errorRequestCoordinator不为空,则创建一个errorRequest,组合mainRequesterrorRequest,返回errorRequestCoordinator

    buildThumbnailRequestRecursive()

    /**
    * 创建略缩图和原图的Request
    */
    private Request buildThumbnailRequestRecursive(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
        if (thumbnailBuilder != null) {
          // Recursive case: contains a potentially recursive thumbnail request builder.
          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<?, ? super TranscodeType> thumbTransitionOptions =
              thumbnailBuilder.transitionOptions;
        
          // Apply our transition by default to thumbnail requests but avoid overriding custom options
          // that may have been applied on the thumbnail request explicitly.
          if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
            thumbTransitionOptions = transitionOptions;
          }
        
          Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
              ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);
        
          int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
          int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
          if (Util.isValidDimensions(overrideWidth, overrideHeight)
              && !thumbnailBuilder.requestOptions.isValidOverride()) {
            thumbOverrideWidth = requestOptions.getOverrideWidth();
            thumbOverrideHeight = requestOptions.getOverrideHeight();
          }
        
          ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
          Request fullRequest =
              obtainRequest(
                  target,
                  targetListener,
                  requestOptions,
                  coordinator,
                  transitionOptions,
                  priority,
                  overrideWidth,
                  overrideHeight);
          isThumbnailBuilt = true;
          // Recursively generate thumbnail requests.
          Request thumbRequest =
              thumbnailBuilder.buildRequestRecursive(
                  target,
                  targetListener,
                  coordinator,
                  thumbTransitionOptions,
                  thumbPriority,
                  thumbOverrideWidth,
                  thumbOverrideHeight,
                  thumbnailBuilder.requestOptions);
          isThumbnailBuilt = false;
          coordinator.setRequests(fullRequest, thumbRequest);
          return coordinator;
        } else if (thumbSizeMultiplier != null) {
          // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
          ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
          Request fullRequest =
              obtainRequest(
                  target,
                  targetListener,
                  requestOptions,
                  coordinator,
                  transitionOptions,
                  priority,
                  overrideWidth,
                  overrideHeight);
          RequestOptions thumbnailOptions = requestOptions.clone()
              .sizeMultiplier(thumbSizeMultiplier);
        
          Request thumbnailRequest =
              obtainRequest(
                  target,
                  targetListener,
                  thumbnailOptions,
                  coordinator,
                  transitionOptions,
                  getThumbnailPriority(priority),
                  overrideWidth,
                  overrideHeight);
        
          coordinator.setRequests(fullRequest, thumbnailRequest);
          return coordinator;
        } else {
          // Base case: no thumbnail.
          // ------------ 重点-------------
          return obtainRequest(
              target,
              targetListener,
              requestOptions,
              parentCoordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight);
        }
    }
    
    • 这个方法,用于创建略缩图和原图的Request,略缩图我们先不管,先看else逻辑obtainRequest()

    obtainRequest()

    /**
    * 生成一个请求,会在池中复用,享元模式
    */
    private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      RequestOptions requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight) {
        //返回Request接口的实现类SingleRequest
        return SingleRequest.obtain(
            context,
            glideContext,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            targetListener,
            requestListeners,
            requestCoordinator,
            glideContext.getEngine(),
            transitionOptions.getTransitionFactory());
    }
    
    • 创建一个SingleRequest实例返回,这里将会回到into()逻辑,RequestManager.track(target, request),这里的Request其实就是SingleRequest

    RequestManager.track(target,request)

    void track(@NonNull Target<?> target, @NonNull Request request) {
        //管理所有请求的状态,在页面生命周期变化时,控制请求做相应的处理
        targetTracker.track(target);
        //发起请求
        requestTracker.runRequest(request);
    }
    
    //管理所有请求的状态,在页面生命周期变化时,控制请求做相应的处理
    public final class TargetTracker implements LifecycleListener {
      private final Set<Target<?>> targets =
          Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());
    
      public void track(@NonNull Target<?> target) {
        targets.add(target);
      }
    
      public void untrack(@NonNull Target<?> target) {
        targets.remove(target);
      }
    
      @Override
      public void onStart() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onStart();
        }
      }
    
      @Override
      public void onStop() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onStop();
        }
      }
    
      @Override
      public void onDestroy() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onDestroy();
        }
      }
    
      @NonNull
      public List<Target<?>> getAll() {
        return Util.getSnapshot(targets);
      }
    
      public void clear() {
        targets.clear();
      }
    }
    
    /**
    * Starts tracking the given request.
    * 开始请求
    */
    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);
        }
    }
    
    • 首先,targetTracker.track(target);,把Target添加到TargetTracker.targets集合中,并在在页面生命周期变化时,控制请求做相应的处理
    • 接着,requestTracker.runRequest(request);,先把SingleRequest添加到RequestTracker.requests队列中,如果当前不是暂停状态状态,那么调用SingleRequest.begin(),如果是暂停状态,则先加入到pendingRequests等待运行的队列中

    SingleRequest.begin()

    @Override
    public void begin() {
        assertNotCallingCallbacks();
        stateVerifier.throwIfRecycled();
        startTime = LogTime.getLogTime();
        //如果model,就是传入的url等资源,为空,则回调加载失败
        if (model == null) {
          if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
            width = overrideWidth;
            height = overrideHeight;
          }
          // Only log at more verbose log levels if the user has set a fallback drawable, because
          // fallback Drawables indicate the user expects null models occasionally.
          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 we're restarted after we're complete (usually via something like a notifyDataSetChanged
        // that starts an identical request into the same Target or View), we can simply use the
        // resource and size we retrieved the last time around and skip obtaining a new size, starting a
        // new load etc. This does mean that users who want to restart a load because they expect that
        // the view size has changed will need to explicitly clear the View or Target before starting
        // the new load.
        if (status == Status.COMPLETE) {
          //如果我们请求完后,想重新开始加载,那么会直接返回已经加载好的资源
          onResourceReady(resource, DataSource.MEMORY_CACHE);
          return;
        }
        
        // Restarts for requests that are neither complete nor running can be treated as new requests
        // and can run again from the beginning.
        
        //Glide对根据ImageView的宽高来进行缓存,所以需要获取ImageView的宽高,overrideWidth和overrideHeight默认为-1
        status = Status.WAITING_FOR_SIZE;
        //第一次请求,是还没有获取宽高的,所以会走else逻辑去获取宽高
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          onSizeReady(overrideWidth, overrideHeight);
        } else {
          //获取ImageView的宽高,target是前面buildImageViewTarget的时候,生成的DrawableImageViewTarget
          //getSize()方法在它的父类ViewTarget中,获取成功会回调当前SingleRequest的onSizeReady()方法
          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));
        }
    }
    
    • 首先,判断model,也就是我们传入的url,是否为空,如果为空,则直接返回,并回调onLoadFailed()
    • 判断当前状态是否是RUNNING状态,如果是,则抛异常,保证一个Request只能同时执行一次
    • 如果是COMMPLETE状态,那么可以直接返回resource,回调onResourceReady,并把获取到的Drawable设置到ImageView上
    • 判断宽高是否有效,如有效,则调用onSizeReady(),开始加载,并设置状态为RUNNING
    • 如果状态为RUNNING,或者为WAITING_FOR_SIZE状态,则显示展位图

    SingleRequest.onSizeReady(width, height)

    /**
    * A callback method that should never be invoked directly.
    * 获取ImageView的宽高成功
    */
    @Override
    public 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);
        
        // This is a hack that's only useful for testing right now where loads complete synchronously
        // even though under any executor running on any thread but the main thread, the load would
        // have completed asynchronously.
        if (status != Status.RUNNING) {
          loadStatus = null;
        }
        if (IS_VERBOSE_LOGGABLE) {
          logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
        }
    }
    
    • 首先,把状态更改为RUNNING
    • 通过Engine.load(),加载图片

    Engine.load()

    public <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) {
    Util.assertMainThread();
        long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
            
        //生成缓存Key,通过这个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;
        }
            
        //2个内存缓存都没有,那么从缓存中,获取一个加载它的EngineJob
        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
        if (current != null) {
          current.addCallback(cb);
          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,用于处理图片
        DecodeJob<R> decodeJob =
            decodeJobFactory.build(
                glideContext,
                model,
                key,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                onlyRetrieveFromCache,
                options,
                engineJob);
            
        //缓存EngineJob,下次可以直接在缓存中取
        jobs.put(key, engineJob);
            
        engineJob.addCallback(cb);
        //把DecodeJob交给EngineJob
        engineJob.start(decodeJob);
            
        if (VERBOSE_IS_LOGGABLE) {
          logWithTimeAndKey("Started new load", startTime, key);
        }
        return new LoadStatus(cb, engineJob);
    }
    
    • 生成EngineKey,用于读取和写入缓存时使用
    • 从缓存中查找,先在ActivityResource活动缓存中查找,再去MemoryCache内存缓存中查找
    • 如果内存缓存没有命中,则开始新的任务
    • jobs.get(key),先从Job缓存Map中查找任务,如果有则直接返回,没有则创建EngineJob
    • EngineJob,用于开启任务,回调资源加载成功或失败
    • 创建DecodeJob,用于加载资源,操作缓存等,将DecodeJobEngineJob通过Callback的形式,绑定起来
    • 调用DecodeJob.start(decodeJob),执行任务
    /**
    * 开始任务
    *
    * @param decodeJob 图片解码DecodeJob
    */
    public void start(DecodeJob<R> decodeJob) {
        this.decodeJob = decodeJob;
        //如果能从磁盘缓存中加载,则使用diskCacheExecutor,否则根据情况判断使用哪个GlideExecutor
        GlideExecutor executor = decodeJob.willDecodeFromCache()
            ? diskCacheExecutor
            : getActiveSourceExecutor();
        //把decodeJob交给GlideExecutor执行,会回调DecodeJob的run()方法
        executor.execute(decodeJob);
    }
    
    • EngineJob.start(),其实就是通过线程池,调用DecodeJobrun()方法

    DecodeJob.run()

    @Override
    public void run() {
        // This should be much more fine grained, but since Java's thread pool implementation silently
        // swallows all otherwise fatal exceptions, this will at least make it obvious to developers
        // that something is failing.
        GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
        // Methods in the try statement can invalidate currentFetcher, so set a local variable here to
        // ensure that the fetcher is cleaned up either way.
        DataFetcher<?> localFetcher = currentFetcher;
        try {
          //如果已经取消,则回调失败
          if (isCancelled) {
            notifyFailed();
            return;
          }
          //运行的核心逻辑,runWrapped()
          runWrapped();
        } catch (Throwable t) {
          // Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
          // usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
          // are however ensuring that our callbacks are always notified when a load fails. Without this
          // notification, uncaught throwables never notify the corresponding callbacks, which can cause
          // loads to silently hang forever, a case that's especially bad for users using Futures on
          // background threads.
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "DecodeJob threw unexpectedly"
                + ", isCancelled: " + isCancelled
                + ", stage: " + stage, t);
          }
          // When we're encoding we've already notified our callback and it isn't safe to do so again.
          if (stage != Stage.ENCODE) {
            throwables.add(t);
            notifyFailed();
          }
          if (!isCancelled) {
            throw t;
          }
        } finally {
          // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
          // close in all cases anyway.
          if (localFetcher != null) {
            localFetcher.cleanup();
          }
          GlideTrace.endSection();
        }
    }
    
    • run()方法,如果任务已取消,则回调失败
    • 核心逻辑,runWrapped()方法

    DecodeJob.runWrapped()

    /**
    * 运行的核心逻辑
    */
    private void runWrapped() {
        switch (runReason) {
          //初始阶段
          case INITIALIZE:
            //获取下一个阶段的状态,返回 RESOURCE_CACHE
            stage = getNextStage(Stage.INITIALIZE);
            //根据下一个阶段的状态,判断出是哪一个Generator来执行,因为是RESOURCE_CACHE,那么这里返回的是ResourceCacheGenerator
            currentGenerator = getNextGenerator();
            //执行Generator
            runGenerators();
            break;
          case SWITCH_TO_SOURCE_SERVICE:
            //尝试从磁盘缓存切到内存缓存
            runGenerators();
            break;
          case DECODE_DATA:
            //解码原数据,也就是去加载资源
            decodeFromRetrievedData();
            break;
          default:
            throw new IllegalStateException("Unrecognized run reason: " + runReason);
        }
    }
    
    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);
        }
    }
    
    /**
    * 获取下一个DataFetcherGenerator
    */
    private DataFetcherGenerator getNextGenerator() {
        //主要看DataFetcherGenerator的startNext()方法
        switch (stage) {
          //ResourceCacheGenerator,寻找是否有经过转换、解码之后的磁盘文件缓存,这个缓存要比源文件缓存小
          case RESOURCE_CACHE:
            return new ResourceCacheGenerator(decodeHelper, this);
          case DATA_CACHE:
            //DataCacheGenerator,寻找源文件磁盘缓存,这个是加载的源文件直接写入缓存
            return new DataCacheGenerator(decodeHelper, this);
          case SOURCE:
            //上面2个缓存Generator都没有命中,则通过SourceGenerator,那么Http请求获取资源,资源请求回来之后先写入磁盘缓存,再返回到Target
            return new SourceGenerator(decodeHelper, this);
          case FINISHED:
            return null;
          default:
            throw new IllegalStateException("Unrecognized stage: " + stage);
        }
    }
    
    private enum RunReason {
        /** The first time we've been submitted. */
        //首次提交任务
        INITIALIZE,
        /**
         * We want to switch from the disk cache service to the source executor.
         * 尝试从磁盘缓存切到内存缓存
         */
        SWITCH_TO_SOURCE_SERVICE,
        /**
         * We retrieved some data on a thread we don't own and want to switch back to our thread to
         * process the data.
         * 解码原数据,也就是去加载资源
         */
        DECODE_DATA,
    }
    
    • RunReason枚举类,有3个状态
      • INITIALIZE,首次提交任务
      • SWITCH_TO_SOURCE_SERVICE,尝试从磁盘缓存切到内存缓存
      • DECODE_DATA,解码原数据,也就是去加载资源

    runWrapped()方法,runReason默认为INITIALIZE,所以我们先看getNextStage(Stage.INITIALIZE)

    • getNextStage(Stage.INITIALIZE),获取下一个阶段,默认缓存都是开的,所以下一个阶段为tage.RESOURCE_CACHE
    • 通过getNextGenerator(),获取DataFetcherGenerator,由于StageRESOURCE_CACHE,那么获取到的是ResourceCacheGenerator,它是从磁盘中获取是否有经过编解码,转码之后的缓存,这个缓存要比源文件缓存小
    • 最后,调用runGenerators()

    DecodeJob.runGenerators()

    /**
    * 执行Generator
    */
    private void runGenerators() {
        currentThread = Thread.currentThread();
        startFetchTime = LogTime.getLogTime();
        boolean isStarted = false;
        while (!isCancelled && currentGenerator != null
                //执行Generator的startNext,这里Generator是ResourceCacheGenerator
                //如果获取不到,则去DataCacheGenerator,从缓存中查找,也找不到则去SourceGenerator
            && !(isStarted = currentGenerator.startNext())) {
          stage = getNextStage(stage);
          currentGenerator = getNextGenerator();
        
          //只有循环到为Stage.SOURCE,才会结束循环
          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.
    }
    
    • 该方法,会进入一个while循环,并通过currentGenerator.startNext(),也就是ResourceCacheGenerator,去查找缓存,如果查找不到缓存,则通过SourceGenerator去执行
    • 直到stageStage.SOURCE,才会停止循环,并调用reschedule()

    EngineJob.reschedule()

    @Override
    public void reschedule() {
        //首先将runReason置为SWITCH_TO_SOURCE_SERVICE,尝试从磁盘缓存切到内存缓存
        runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
        //callback就是EngineJob,所以回到EngineJob.reschedule()方法
        callback.reschedule(this);
    }
    
    • 首先将runReason置为SWITCH_TO_SOURCE_SERVICE,尝试从磁盘缓存切到内存缓存
    • 调用callback.reschedule(this);,这个callback就是EngineJob,所以又回到EngineJob.reschedule()方法

    EngineJob.reschedule()

    @Override
    public void reschedule(DecodeJob<?> job) {
        // Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself
        // up.
        getActiveSourceExecutor().execute(job);
    }
    
    • 通过getActiveSourceExecutor()拿到sourceExecutor线程池,执行DecodeJob
    • 又会回到DecodeJob.run()方法,此时runReason已经为SWITCH_TO_SOURCE_SERVICE,并且stageSOURCE
    • DecodeJob.runGenerators()方法中,currentGenerator已经为DataSourceGenerator,它会查找是否有源文件缓存,有则直接返回,没有则通过SourceGenerator去加载资源

    ResourceCacheGenerator.startNext()

    @Override
    public boolean startNext() {
        //获取缓存Key,会返回GlideUrl
        List<Key> sourceIds = helper.getCacheKeys();
        if (sourceIds.isEmpty()) {
          return false;
        }
        //获取3个可以到达的registeredResourceClasses,GifDrawable、Bitmap、BitmapDrawable
        List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
        if (resourceClasses.isEmpty()) {
          if (File.class.equals(helper.getTranscodeClass())) {
            return false;
          }
          // TODO(b/73882030): This case gets triggered when it shouldn't. With this assertion it causes
          // all loads to fail. Without this assertion it causes loads to miss the disk cache
          // unnecessarily
          // throw new IllegalStateException(
          //    "Failed to find any load path from " + helper.getModelClass() + " to "
          //        + helper.getTranscodeClass());
        }
        while (modelLoaders == null || !hasNextModelLoader()) {
          resourceClassIndex++;
          if (resourceClassIndex >= resourceClasses.size()) {
            sourceIdIndex++;
            if (sourceIdIndex >= sourceIds.size()) {
              //如果是第一次请求,就会在这里返回
              return false;
            }
            resourceClassIndex = 0;
          }
        
          Key sourceId = sourceIds.get(sourceIdIndex);
          Class<?> resourceClass = resourceClasses.get(resourceClassIndex);
          Transformation<?> transformation = helper.getTransformation(resourceClass);
          // PMD.AvoidInstantiatingObjectsInLoops Each iteration is comparatively expensive anyway,
          // we only run until the first one succeeds, the loop runs for only a limited
          // number of iterations on the order of 10-20 in the worst case.
          currentKey =
              new ResourceCacheKey(// NOPMD AvoidInstantiatingObjectsInLoops
                  helper.getArrayPool(),
                  sourceId,
                  helper.getSignature(),
                  helper.getWidth(),
                  helper.getHeight(),
                  transformation,
                  resourceClass,
                  helper.getOptions());
          cacheFile = helper.getDiskCache().get(currentKey);
          if (cacheFile != null) {
            sourceKey = sourceId;
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
          }
        }
        
        loadData = null;
        boolean started = false;
        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;
    }
    
    • 先从ResourceCacheGenerator中去寻找是否有经过转换、解码之后的磁盘文件缓存,这个缓存要比源文件缓存小

    DataSourceGenerator.startNext()

    @Override
    public boolean startNext() {
        //如果能从缓存中获取文件,能找到就返回,否则进去到下一个Generator,下一个是SourceGenerator
        while (modelLoaders == null || !hasNextModelLoader()) {
          sourceIdIndex++;
          if (sourceIdIndex >= cacheKeys.size()) {
            return false;
          }
        
          Key sourceId = cacheKeys.get(sourceIdIndex);
          // PMD.AvoidInstantiatingObjectsInLoops The loop iterates a limited number of times
          // and the actions it performs are much more expensive than a single allocation.
          @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
          Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
          cacheFile = helper.getDiskCache().get(originalKey);
          if (cacheFile != null) {
            this.sourceKey = sourceId;
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
          }
        }
        
        loadData = null;
        boolean started = false;
        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;
    }
    
    • 再从DataSourceGenerator中寻找源文件磁盘缓存,这个是加载的源文件直接写入缓存;

    SourceGenerator.startNext()

    @Override
    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;
    while (!started && hasNextModelLoader()) {
      //获取一个ModelLoader加载器
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        //fetcher是HttpUrlFetcher,通过它来请求数据,同时设置回调callback为自身,回调到自身实现的onDataReady()
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
    }
    
    • 如果都没命中,那么就去Http请求资源,资源请求回来之后先写入磁盘缓存,再返回到Target。

    HttpUrlFetcher.loadData()

    //--------------------- HttpUrlFetcher ---------------------
    @Override
    public void loadData(@NonNull Priority priority,
      @NonNull DataCallback<? super InputStream> callback) {
        long startTime = LogTime.getLogTime();
        try {
          //通过loadDataWithRedirects(),请求回来的数据转换为InputStream,回调给callback
          InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
          //回调onDataReady()
          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));
          }
        }
    }
    
    /**
    * 请求数据,通过HttpURLConnection
    */
    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 {
          // Comparing the URLs using .equals performs additional network I/O and is generally broken.
          // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
          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);
        
        // Stop the urlConnection instance of HttpUrlConnection from following redirects so that
        // redirects will be handled by recursive calls to this method, loadDataWithRedirects.
        urlConnection.setInstanceFollowRedirects(false);
        
        // Connect explicitly to avoid errors in decoders if connection fails.
        urlConnection.connect();
        // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
        stream = urlConnection.getInputStream();
        if (isCancelled) {
          return null;
        }
        final int statusCode = urlConnection.getResponseCode();
        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);
          // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
          // to disconnecting the url connection below. See #2352.
          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);
        }
    }
    
    //--------------------- SourceGenerator ---------------------
    Override
    public void onDataReady(Object data) {
      DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
      if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
        dataToCache = data;
        // We might be being called back on someone else's thread. Before doing anything, we should
        // reschedule to get back onto Glide's thread.
        cb.reschedule();
      } else {
        cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
            loadData.fetcher.getDataSource(), originalKey);
      }
    }
    
    • HttpUrlFetcher,通过HttpURLConnection发起请求,并把数据转换为InputStream
    • 获取数据成功,回调callback.onDataReady,这callback是SourceGenerator,然后回调cb.onDataFetcherReady,这个cb是DecodeJob,所以回调到DecodeJob.onDataFetcherReady ()

    DecodeJob.onDataFetcherReady()

    @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();
          }
        }
    }
    
    /**
    * 解析获取到的数据
    */
    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 {
          //通过decodeFromData()获取Resource
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
        } catch (GlideException e) {
          e.setLoggingDetails(currentAttemptingKey, currentDataSource);
          throwables.add(e);
        }
        //解析完成,通知下去
        if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
    }
    
    /**
    * 通知调用层,数据已经准备好了
    */
    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();
          }
        }
        // Call onEncodeComplete outside the finally block so that it's not called if the encode process
        // throws.
        //通知解码完成
        onEncodeComplete();
    }
    
    /**
    * 通知调用层,数据已经准备好了
    */
    private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
        //这个Callback是EngineJob
        callback.onResourceReady(resource, dataSource);
    }
    
    • 最后回调callback.onResourceReady(),其实就是EngineJob.onResourceReady()

    EngineJob.onResourceReady()

    @Override
    public void onResourceReady(Resource<R> resource, DataSource dataSource) {
        this.resource = resource;
        this.dataSource = dataSource;
        //在主线程回调中,通知上层Engine任务完成了
        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
    }
    
    private static class MainThreadCallback implements Handler.Callback {
        @Synthetic
        @SuppressWarnings("WeakerAccess")
        MainThreadCallback() { }
        
        @Override
        public boolean handleMessage(Message message) {
          EngineJob<?> job = (EngineJob<?>) message.obj;
          switch (message.what) {
            case MSG_COMPLETE:
              //通知Engine,任务完成了
              job.handleResultOnMainThread();
              break;
            case MSG_EXCEPTION:
              job.handleExceptionOnMainThread();
              break;
            case MSG_CANCELLED:
              job.handleCancelledOnMainThread();
              break;
            default:
              throw new IllegalStateException("Unrecognized message: " + message.what);
          }
          return true;
        }
    }
    
    @Synthetic
    void handleResultOnMainThread() {
        stateVerifier.throwIfRecycled();
        if (isCancelled) {
          resource.recycle();
          release(false /*isRemovedFromQueue*/);
          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 = engineResourceFactory.build(resource, isCacheable);
        hasResource = true;
        
        // Hold on to resource for duration of request so we don't recycle it in the middle of
        // notifying if it synchronously released by one of the callbacks.
        engineResource.acquire();
        //回调Engine层,任务完成
        listener.onEngineJobComplete(this, key, engineResource);
        
        //noinspection ForLoopReplaceableByForEach to improve perf
        for (int i = 0, size = cbs.size(); i < size; i++) {
          ResourceCallback cb = cbs.get(i);
          if (!isInIgnoredCallbacks(cb)) {
            engineResource.acquire();
            //回调给SingleRequest,通知资源获取到了
            cb.onResourceReady(engineResource, dataSource);
          }
        }
        // Our request is complete, so we can release the resource.
        engineResource.release();
        
        release(false /*isRemovedFromQueue*/);
    }
    
    • 通过Handler,把加载结果回调给Engine
    • 并且回调SingleRequest.onResourceReady()

    SingleRequest.onResourceReady()

    @Override
    public 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;
        }
            
        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);
          // We can't put the status to complete before asking canSetResource().
          status = Status.COMPLETE;
          return;
        }
            
        //继续通知资源准备好了
        onResourceReady((Resource<R>) resource, (R) received, dataSource);
    }
    
    private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
        // We must call isFirstReadyResource before setting status.
        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);
            //通知ImageViewTarget,资源加载完成
            target.onResourceReady(result, animation);
          }
        } finally {
          isCallingCallbacks = false;
        }
        
        notifyLoadSuccess();
    }
    
    • 回调给ImageViewTarget.onResourceReady(),告知资源加载完成

    ImageViewTarget.onResourceReady()

    @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) {
        // Order matters here. Set the resource first to make sure that the Drawable has a valid and
        // non-null Callback before starting it.
        //setResource()是一个抽象方法,由子类去实现,例如DrawableImageViewTarget
        setResource(resource);
        maybeUpdateAnimatable(resource);
    }
    
    protected abstract void setResource(@Nullable Z resource);
    
    • 回调子类的setResource()方法,该方法被BitmapImageViewTargetDrawableImageViewTarget实现,例如我们传入字符串的url,ViewTarget就为DrawableImageViewTarget

    DrawableImageViewTarget.setResource()

    @Override
    protected void setResource(@Nullable Drawable resource) {
        //设置资源到ImageView
        view.setImageDrawable(resource);
    }
    
    • 最后,把Drawbale,设置到了ImageView上。

    相关文章

      网友评论

        本文标题:Glide加载流程源码分析

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