美文网首页
Glide源码分析-网络图片加载主流程分析

Glide源码分析-网络图片加载主流程分析

作者: Joker_Wan | 来源:发表于2021-02-09 18:19 被阅读0次

    第一节,我们主要分析
    Glide.with(this)
    .load(url)
    .into(imageView)
    这三步,也就是最简单的将一个网络图片展示在ImageView上的三步。

    1 Glide.with

    Glide.with 重载方法较多

    public class Glide implements ComponentCallbacks2 {
        ...
        @NonNull
        public static RequestManager with(@NonNull Context context) {
            return getRetriever(context).get(context);
        }
    
        @NonNull
        public static RequestManager with(@NonNull Activity activity) {
            return getRetriever(activity).get(activity);
        }
    
        @NonNull
        public static RequestManager with(@NonNull FragmentActivity activity) {
            return getRetriever(activity).get(activity);
        }
    
        @NonNull
        public static RequestManager with(@NonNull Fragment fragment) {
            return getRetriever(fragment.getActivity()).get(fragment);
        }
    
        @SuppressWarnings("deprecation")
        @Deprecated
        @NonNull
        public static RequestManager with(@NonNull android.app.Fragment fragment) {
            return getRetriever(fragment.getActivity()).get(fragment);
        }
    
        @NonNull
        public static RequestManager with(@NonNull View view) {
            return getRetriever(view.getContext()).get(view);
        }
    }
    

    每个重载方法内部都首先调用getRetriever(@Nullable Context context)方法获取一个RequestManagerRetriever对象,然后调用其get方法来返回RequestManager。先来看Glide.getRetriever

      @NonNull
      private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        // 此处省略对context判空代码
        // ...
        
        return Glide.get(context).getRequestManagerRetriever();
      }
    

    方法里调用了Glide.get(context)创建了一个Glide,接着调用 Glide的getRequestManagerRetriever()返回RequestManagerRetriever对象。看下Glide.get(context)

      @NonNull
      public static Glide get(@NonNull Context context) {
        if (glide == null) {
          synchronized (Glide.class) {
            if (glide == null) {
              checkAndInitializeGlide(context);
            }
          }
        }
    
        return glide;
      }
      
        private static void checkAndInitializeGlide(@NonNull Context context) {
        // 保证只创建一个Glide实例
        if (isInitializing) {
          throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
        }
        isInitializing = true;
        initializeGlide(context);
        isInitializing = false;
      }
    

    这里是创建一个 Glide 单例对象,具体创建过程在initializeGlide(context)

      private static void initializeGlide(@NonNull Context context) {
        initializeGlide(context, new GlideBuilder());
      }
    
      @SuppressWarnings("deprecation")
      private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
        Context applicationContext = context.getApplicationContext();
        
        // 如果有配置@GlideModule注解,那么会反射构造kapt生成的GeneratedAppGlideModuleImpl类
        GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
        
        // 如果Impl存在,且允许解析manifest文件,则遍历manifest中的meta-data,解析出所有的GlideModule类
        List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
        if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
          manifestModules = new ManifestParser(applicationContext).parse();
        }
    
        // ... 此处省略根据Impl的黑名单,剔除manifest中的GlideModule类相关代码
    
        // 如果Impl存在,那么设置为该类的RequestManagerFactory; 否则,设置为null
        RequestManagerRetriever.RequestManagerFactory factory =
            annotationGeneratedModule != null
                ? annotationGeneratedModule.getRequestManagerFactory() : null;
        builder.setRequestManagerFactory(factory);
        
        // 依次调用manifest中GlideModule类的applyOptions方法,将配置写到builder里
        for (com.bumptech.glide.module.GlideModule module : manifestModules) {
          module.applyOptions(applicationContext, builder);
        }
        
        // 写入Impl的配置,会覆盖掉manifest中的配置
        if (annotationGeneratedModule != null) {
          annotationGeneratedModule.applyOptions(applicationContext, builder);
        }
        
        // 调用GlideBuilder.build方法创建Glide
        Glide glide = builder.build(applicationContext);
        
        // 依次调用manifest中GlideModule类的registerComponents方法,来替换Glide的默认配置
        for (com.bumptech.glide.module.GlideModule module : manifestModules) {
          module.registerComponents(applicationContext, glide, glide.registry);
        }
        // 调用Impl中替换Glide配置的方法
        if (annotationGeneratedModule != null) {
            annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
        }
        
        // 注册内存管理的回调,因为Glide实现了ComponentCallbacks2接口
        applicationContext.registerComponentCallbacks(glide);
        // 保存glide实例到静态变量中
        Glide.glide = glide;
      }
    

    我们主要分析其中三步主流程,并没有 在 AndroidManifest 中配置meta-data,也没有配置@GlideModule 注解,所以初始化的代码可以简化如下:

      @SuppressWarnings("deprecation")
      private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
        Context applicationContext = context.getApplicationContext();
        // 调用GlideBuilder.build方法创建Glide
        Glide glide = builder.build(applicationContext);
        // 注册内存管理的回调,Glide实现了ComponentCallbacks2
        applicationContext.registerComponentCallbacks(glide);
        // 保存glide实例到静态变量中
        Glide.glide = glide;
      }
    

    继续跟进下GlideBuilder.build方法

    @NonNull
      Glide build(@NonNull Context context) {
      
        // 此处省略构造Glide需要依赖的其他对象的实例化代码
        // ...
        
        RequestManagerRetriever requestManagerRetriever =
            new RequestManagerRetriever(requestManagerFactory);
    
        return new Glide(
            context,
            engine,
            memoryCache,
            bitmapPool,
            arrayPool,
            requestManagerRetriever,
            connectivityMonitorFactory,
            logLevel,
            defaultRequestOptions.lock(),
            defaultTransitionOptions,
            defaultRequestListeners,
            isLoggingRequestOriginsEnabled);
      }
    

    这里重点看下requestManagerRetriever的初始化,requestManagerRetriever通过其构造器初始化并传入的requestManagerFactory,然后作为入参传入Glide构造器。跟进RequestManagerRetriever构造器

      public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
        this.factory = factory != null ? factory : DEFAULT_FACTORY;
        handler = new Handler(Looper.getMainLooper(), this /* Callback */);
      }
    

    当传进来的factory为null时会用默认的 DEFAULT_FACTORY

      private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
        @NonNull
        @Override
        public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
            @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
          return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
      };
    

    DEFAULT_FACTORY 中build方法会构造 RequestManager 对象。回到 Glide.with 方法中,接着调用RequestManagerRetriever.get方法,并传入对生命周期可感知的入参,这里的入参有 Context、Activity、Fragment、View

    @NonNull
    private RequestManager getApplicationManager(@NonNull Context context) {
      // Either an application context or we're on a background thread.
      if (applicationManager == null) {
        synchronized (this) {
          if (applicationManager == null) {
            Glide glide = Glide.get(context.getApplicationContext());
            applicationManager =
                factory.build(
                    glide,
                    new ApplicationLifecycle(),
                    new EmptyRequestManagerTreeNode(),
                    context.getApplicationContext());
          }
        }
      }
      return applicationManager;
    }
    
    @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)) {
        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());
        }
      }
      return getApplicationManager(context);
    }
    
    @NonNull
    public RequestManager get(@NonNull FragmentActivity activity) {
      if (Util.isOnBackgroundThread()) {
        return get(activity.getApplicationContext());
      } else {
        assertNotDestroyed(activity);
        FragmentManager fm = activity.getSupportFragmentManager();
        return supportFragmentGet(
            activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
      }
    }
    
    @NonNull
    public RequestManager get(@NonNull Fragment fragment) {
      Preconditions.checkNotNull(fragment.getActivity(),
            "You cannot start a load on a fragment before it is attached or after it is destroyed");
      if (Util.isOnBackgroundThread()) {
        return get(fragment.getActivity().getApplicationContext());
      } else {
        FragmentManager fm = fragment.getChildFragmentManager();
        return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
      }
    }
    
    @SuppressWarnings("deprecation")
    @NonNull
    public RequestManager get(@NonNull Activity activity) {
      if (Util.isOnBackgroundThread()) {
        return get(activity.getApplicationContext());
      } else {
        assertNotDestroyed(activity);
        android.app.FragmentManager fm = activity.getFragmentManager();
        return fragmentGet(
            activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
      }
    }
    
    @SuppressWarnings("deprecation")
    @NonNull
    public RequestManager get(@NonNull View view) {
      if (Util.isOnBackgroundThread()) {
        return get(view.getContext().getApplicationContext());
      }
    
      // 省略 checkNotNull
    
      // 找出View所在的Fragment或Activity
      if (activity instanceof FragmentActivity) {
        Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
        return fragment != null ? get(fragment) : get(activity);
      }
    
      // Standard Fragments.
      android.app.Fragment fragment = findFragment(view, activity);
      if (fragment == null) {
        return get(activity);
      }
      return get(fragment);
    }
    

    这些get方法中先判断是否是后台线程,如果是后台线程,最终会直接调用 getApplicationManager(context) 给 applicationManager 赋值并将其返回,applicationManager是RequestManager类型的对象。初始化 applicationManager 的代码如下:

            Glide glide = Glide.get(context.getApplicationContext());
            applicationManager =
                factory.build(
                    glide,
                    new ApplicationLifecycle(),
                    new EmptyRequestManagerTreeNode(),
                    context.getApplicationContext());
    

    其中 factory 就是 DEFAULT_FACTORY,DEFAULT_FACTORY 的 build方法会构造并返回的是一个 RequestManager 对象,所以 applicationManager 初始化代码可以简化如下:

    applicationManager =
                RequestManager(
                    glide,
                    new ApplicationLifecycle(),
                    new EmptyRequestManagerTreeNode(),
                    context.getApplicationContext());
    

    继续回到RequestManagerRetriever.get重载方法,如果当前线程不是后台线程,get(View)和get(Context)会根据情况调用get(Fragment)或get(FragmentActivity),get(View)最终也会通过一系列的操作去找到上层的Fragment或者Activity 然后调用get(Fragment)或get(FragmentActivity),由于通过View寻找上层的Fragment或者Activity 的过程开销相对较大,不建议传入View对象。get(Fragment)和get(FragmentActivity)方法都会调用supportFragmentGet方法,supportFragmentGet方法如下:

      @NonNull
      private RequestManager supportFragmentGet(
          @NonNull Context context,
          @NonNull FragmentManager fm,
          @Nullable Fragment parentHint,
          boolean isParentVisible) {
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        RequestManager requestManager = current.getRequestManager();
        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);
          current.setRequestManager(requestManager);
        }
        return requestManager;
      }
    

    Glide会使用一个加载目标所在的宿主Activity或Fragment的子Fragment来安全保存一个RequestManager,而RequestManager被Glide用来开始、停止、管理Glide请求。也就是说利用给宿主添加一个子Fragment来间接的获取宿主的生命周期,从而保证Glide请求与生命周期同步。

    supportFragmentGet就是创建/获取这个子Fragment,即 SupportRequestManagerFragment,并返回 RequestManager 实例。跟进RequestManagerRetriever.getSupportRequestManagerFragment

    @NonNull
      private SupportRequestManagerFragment getSupportRequestManagerFragment(
          @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingSupportRequestManagerFragments.get(fm);
          if (current == null) {
            current = new SupportRequestManagerFragment();
            // 对于fragment来说,此方法会以Activity为host创建另外一个SupportRequestManagerFragment
            // 作为rootRequestManagerFragment
            // 并会将current加入到rootRequestManagerFragment的childRequestManagerFragments中
            // 在RequestManager递归管理请求时会使用到
            current.setParentFragmentHint(parentHint);
            // 如果当前页面是可见的,那么调用其lifecycle的onStart方法
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            pendingSupportRequestManagerFragments.put(fm, current);
            // 将fragment添加到页面中
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    

    如果之前已经添加过SupportRequestManagerFragment则直接返回添加过的Fragment,否则从 map中获取获取,取到了也直接返回,取不到就通过构造器创建一个对象,然后将此Fragment添加到宿主Activity或Fragment中。

    到这里 Glide.with方法分析完毕,主要就是创建 Glide 单例,并通过向宿主(Fragment/Activity)添加一个空的Fragment来关联宿主的生命周期用来管理Glide请求,然后返回一个具体管理Glide请求的 RequestManager 对象。

    2 RequestManager.load

    RequestManager.load也有许多重载的方法

    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
      return asDrawable().load(bitmap);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
      return asDrawable().load(drawable);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable String string) {
      return asDrawable().load(string);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable Uri uri) {
      return asDrawable().load(uri);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable File file) {
      return asDrawable().load(file);
    }
    
    @SuppressWarnings("deprecation")
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
      return asDrawable().load(resourceId);
    }
    
    @SuppressWarnings("deprecation")
    @CheckResult
    @Override
    @Deprecated
    public RequestBuilder<Drawable> load(@Nullable URL url) {
      return asDrawable().load(url);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable byte[] model) {
      return asDrawable().load(model);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable Object model) {
      return asDrawable().load(model);
    }
    

    所有的重载方法中都调用了asDrawable()方法得到一个RequestBuilder对象,然后再调用RequestBuilder.load方法。asDrawable()方法与asGif()、asBitmap()、asFile()等方法一样,都会调用RequestManager.as()方法生成一个RequestBuilder<ResourceType>对象,然后再调用apply方法添加不同的requestOptions,代码如下:

    @NonNull
    @CheckResult
    public RequestBuilder<Bitmap> asBitmap() {
      return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
    }
    
    @NonNull
    @CheckResult
    public RequestBuilder<GifDrawable> asGif() {
      return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
    }  
    
    @NonNull
    @CheckResult
    public RequestBuilder<Drawable> asDrawable() {
      return as(Drawable.class);
    }
    
    @NonNull
    @CheckResult
    public RequestBuilder<File> asFile() {
      return as(File.class).apply(skipMemoryCacheOf(true));
    }
    
    @NonNull
    @CheckResult
    public <ResourceType> RequestBuilder<ResourceType> as(
        @NonNull Class<ResourceType> resourceClass) {
      return new RequestBuilder<>(glide, this, resourceClass, context);
    }
    

    在RequestBuilder的构造器方法方法中将Drawable.class这样的入参保存到了transcodeClass变量中。继续跟进RequestBuilder.load,RequestBuilder.load 也有很多方法的重载:

    @NonNull
    @CheckResult
    @SuppressWarnings("unchecked")
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable Object model) {
      return loadGeneric(model);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
      return loadGeneric(bitmap)
          .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
      return loadGeneric(drawable)
          .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
      return loadGeneric(uri);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable File file) {
      return loadGeneric(file);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
      return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
    }
    
    @Deprecated
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable URL url) {
      return loadGeneric(url);
    }
    
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable byte[] model) {
      RequestBuilder<TranscodeType> result = loadGeneric(model);
      if (!result.isDiskCacheStrategySet()) {
          result = result.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
      }
      if (!result.isSkipMemoryCacheSet()) {
        result = result.apply(skipMemoryCacheOf(true /*skipMemoryCache*/));
      }
      return result;
    }
    
    @NonNull
    private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
      this.model = model;
      isModelSet = true;
      return this;
    }
    

    每个重载方法中都会调用loadGeneric保存传递的参数到 model 中并设置isModelSet=true,部分方法会apply额外的requestOptions。

    总结一下:RequestManager.load方法中主要就是构造RequestBuilder并将load的资源保存到RequestBuilder中的 model 变量中。

    3 RequestBuilder.into

    RequestBuilder.into方法的重载也比较多,我们常用的是into(imageView),代码如下:

    @NonNull
      public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
        Util.assertMainThread();
        Preconditions.checkNotNull(view);
    
        BaseRequestOptions<?> requestOptions = this;
        
        // 若没有指定transform,isTransformationSet()为false
        // isTransformationAllowed()一般为true,除非主动调用了dontTransform()方法
        if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
          
          // 根据ImageView的ScaleType设置不同的 downsample 和transform 选项对图片进行剪裁
          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.
          }
        }
    
        return into(
            glideContext.buildImageViewTarget(view, transcodeClass),
            /*targetListener=*/ null,
            requestOptions,
            Executors.mainThreadExecutor());
      }
    

    into(ImageView)方法里面会先判断需不需要对图片进行裁切,然后调用into重载方法。into重载方法第一个参数glideContext.buildImageViewTarget(view, transcodeClass)代码如下:

    // GlideContext
    @NonNull
    public <X> ViewTarget<ImageView, X> buildImageViewTarget(
        @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
      // imageViewTargetFactory是ImageViewTargetFactory的一个实例
      // transcodeClass在RequestManager.load方法中确定了,就是Drawable.class
      return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
    }
    
    // ImageViewTargetFactory
    @NonNull
    @SuppressWarnings("unchecked")
    public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
        @NonNull Class<Z> clazz) {
      if (Bitmap.class.equals(clazz)) {
        return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
      } else if (Drawable.class.isAssignableFrom(clazz)) {
        // 返回的是(ViewTarget<ImageView, Drawable>) new DrawableImageViewTarget(view);
        return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
      } else {
        throw new IllegalArgumentException(
            "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
      }
    }
    

    因为我们这里要转码的类型为:Drawable.class,所以buildTarget返回的是DrawableImageViewTarget对象,所以第一个参数等价于

    (ViewTarget<ImageView, Drawable>) new DrawableImageViewTarget(view)
    

    第四个参数Executors.mainThreadExecutor()是一个Executor,内部使用MainLooper的Handler,当执行Executor.execute(Runnable)方法时将Runnable使用此 Handler post 出去。

      /** Posts executions to the main thread. */
      public static Executor mainThreadExecutor() {
        return MAIN_THREAD_EXECUTOR;
      }
    
        private static final Executor MAIN_THREAD_EXECUTOR =
          new Executor() {
            private final Handler handler = new Handler(Looper.getMainLooper());
    
            @Override
            public void execute(@NonNull Runnable command) {
              handler.post(command);
            }
        };
    

    分析完了参数,继续分析into 重载方法内部实现

    private <Y extends Target<TranscodeType>> Y into(
        @NonNull Y target,
        @Nullable RequestListener<TranscodeType> targetListener,
        BaseRequestOptions<?> options,
        Executor callbackExecutor) {
    
      if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
      }
    
      // 创建了一个SingleRequest
      Request request = buildRequest(target, targetListener, options, callbackExecutor);
    
      // 这里会判断需不需要重新开始任务
      // 如果当前request和target上之前的request previous相等
      // 且设置了忽略内存缓存或previous还没有完成
      // 那么会进入if分支
      Request previous = target.getRequest();
      if (request.isEquivalentTo(previous)
          && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        request.recycle();
        
        // 如果正在运行,就不管它;如果已经失败了,就重新开始
        if (!Preconditions.checkNotNull(previous).isRunning()) {
            previous.begin();
        }
        return target;
      }
    
      // 如果不能复用previous
      // 先清除target上之前的Request
      requestManager.clear(target);
      // 将Request作为tag设置到view中
      target.setRequest(request);
      // 真正开始网络图片的加载
      requestManager.track(target, request);
    
      return target;
    }
    

    先看一下buildRequest(target, targetListener, options, callbackExecutor)如何创建SingleRequest,方法调用链为:buildRequest->buildRequestRecursive->buildThumbnailRequestRecursive->obtainRequest:

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

    最终通过SingleRequest.obtain方法传递参数构建SingleRequest对象。继续回到into重载方法中调用requestManager.track(target, request)进行网络图片的加载。

      synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
        targetTracker.track(target);
        requestTracker.runRequest(request);
      }
    

    targetTracker成员变量在声明的时候直接初始化为TargetTracker类的无参数实例,该类的作用是保存所有的Target并向它们转发生命周期事件.requestTracker在RequestManager的构造器中传入了new RequestTracker(),该类的作用管理所有状态的请求。继续跟进requestTracker.runRequest(request)

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

    isPaused默认为false,只有调用了RequestTracker.pauseRequests或RequestTracker.pauseAllRequests后才会为true。因此,下面会执行request.begin()方法,这里的request就是在into重载方法里面构造出来的 SingleRequest,跟进SingleRequest.begin

    @Override
      public synchronized void begin() {
      
        //...
        
        // 如果model为空,会调用监听器的onLoadFailed处理
        // 若无法处理,则展示失败时的占位图
        if (model == null) {
          ...
          onLoadFailed(new GlideException("Received null model"), logLevel);
          return;
        }
    
        if (status == Status.RUNNING) {
          throw new IllegalArgumentException("Cannot restart a running request");
        }
    
        // 如果已经加载过,再次在相同的目标或视图中加载相同的请求,在重新来加载前清除View或Target
        if (status == Status.COMPLETE) {
          onResourceReady(resource, DataSource.MEMORY_CACHE);
          return;
        }
    
        // 如果指定了overrideWidth和overrideHeight,那么直接调用onSizeReady方法
        // 否则会获取ImageView的宽、高,然后调用onSizeReady方法
        // 在该方法中会创建图片加载的Job并开始执行
        status = Status.WAITING_FOR_SIZE;
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          onSizeReady(overrideWidth, overrideHeight);
        } else {
          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 == null会调用onLoadFailed方法,在其内部会调用监听器的onLoadFailed处理,若无法处理,则展示失败时的占位图。如果指定了overrideWidth和overrideHeight,那么直接调用onSizeReady方法,否则会获取ImageView的宽、高,然后调用onSizeReady方法,在该方法中会创建图片加载的Job并开始执行。我们先来看下 SingleRequest.onSizeReady:

    @Override
      public synchronized void onSizeReady(int width, int height) {
        
        ...
        
        // 在SingleRequest.begin方法中已经将status设置为WAITING_FOR_SIZE状态了
        if (status != Status.WAITING_FOR_SIZE) {
          return;
        }
        
        // 设置状态为RUNNING
        status = Status.RUNNING;
    
        // 将原始尺寸与0~1之间的系数相乘,取最接近的整数值,得到新的尺寸
        float sizeMultiplier = requestOptions.getSizeMultiplier();
        this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
        this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
    
        ...
        
        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);
    
        ...
      }
    

    最后会调用engine.load方法,Engine是负责加载,管理active、cached状态资源的类。在GlideBuilder.build中创建Glide时,若没有主动设置engine,会使用下面的参数进行创建

    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
    
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }
    

    继续跟进Engine.load方法

    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);
    
        // 从active资源中进行加载
        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;
        }
    
        // 从内存cache资源中进行加载
        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;
        }
    
        // 从正在进行的jobs中进行加载
        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
        if (current != null) {
          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,该类实现了Runnable接口
        DecodeJob<R> decodeJob =
            decodeJobFactory.build(
                glideContext,
                model,
                key,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                onlyRetrieveFromCache,
                options,
                engineJob);
    
        // 根据engineJob.onlyRetrieveFromCache的值是否为true
        // 将engineJob保存到onlyCacheJobs或者jobs HashMap中
        jobs.put(key, engineJob);
    
        // 添加资源加载状态回调,参数会包装成ResourceCallbackAndExecutor类型
        // 并保存到ResourceCallbacksAndExecutors.callbacksAndExecutors中
        engineJob.addCallback(cb, callbackExecutor);
        
        // 开始执行decodeJob任务
        engineJob.start(decodeJob);
    
        ...
        
        return new LoadStatus(cb, engineJob);
      }
    

    Engine.load方法中会以一些参数作为key,依次从active状态、cached状态和进行中的 jobs 里寻找。若没有找到,则会创建对应的job并开始执行。engineJobFactorydecodeJobFactory 需要注意的是里面使用了对象池 Pools.Pool 来复用 Job对象内存,Pools.Pool里面通过Object[]来保存Job。继续跟进 engineJob.start(decodeJob):

      // EngineJob
      public synchronized void start(DecodeJob<R> decodeJob) {
        this.decodeJob = decodeJob;
        GlideExecutor executor = decodeJob.willDecodeFromCache()
            ? diskCacheExecutor
            : getActiveSourceExecutor();
        executor.execute(decodeJob);
      }
    

    由于我们没有配置缓存策略,默认会使用缓存,所以decodeJob.willDecodeFromCache()为true,那么就使用diskCacheExecutor 来执行decodeJob。diskCacheExecutor 默认值为GlideExecutor.newDiskCacheExecutor(),这是类似于一个SingleThreadExecutor的线程池,这里使用了设计模式中的代理模式:

    /**
     * A prioritized {@link ThreadPoolExecutor} for running jobs in Glide.
     */
    public final class GlideExecutor implements ExecutorService {
      private static final String DEFAULT_DISK_CACHE_EXECUTOR_NAME = "disk-cache";
      private static final int DEFAULT_DISK_CACHE_EXECUTOR_THREADS = 1;
    
      private final ExecutorService delegate;
    
      public static GlideExecutor newDiskCacheExecutor() {
        return newDiskCacheExecutor(
            DEFAULT_DISK_CACHE_EXECUTOR_THREADS,
            DEFAULT_DISK_CACHE_EXECUTOR_NAME,
            UncaughtThrowableStrategy.DEFAULT);
      }
    
      public static GlideExecutor newDiskCacheExecutor(
          int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) {
        return new GlideExecutor(
            new ThreadPoolExecutor(
                threadCount /* corePoolSize */,
                threadCount /* maximumPoolSize */,
                0 /* keepAliveTime */,
                TimeUnit.MILLISECONDS,
                new PriorityBlockingQueue<Runnable>(),
                new DefaultThreadFactory(name, uncaughtThrowableStrategy, true)));
      }
    
      @VisibleForTesting
      GlideExecutor(ExecutorService delegate) {
        this.delegate = delegate;
      }
    
      @Override
      public void execute(@NonNull Runnable command) {
        delegate.execute(command);
      }
    
      @NonNull
      @Override
      public Future<?> submit(@NonNull Runnable task) {
        return delegate.submit(task);
      }
      ...
    }
    

    至此,decodeJob已经提交到了线程池中。回到SingleRequest.begin 继续跟进后面的代码

    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      target.onLoadStarted(getPlaceholderDrawable());
    }
    

    由于此时status == Status.RUNNING为true,现在开始展示placeholder。

    前面我们已经将decodeJob已经提交到了线程池中,那么继续分析DecodeJob.run方法

    @Override
      public void run() {
        ...
        try {
          if (isCancelled) {
            notifyFailed();
            return;
          }
          
          runWrapped();
        } catch (CallbackException e) {
          throw e;
        } catch (Throwable t) {
          ...
          throw t;
        } finally {
           ...
        }
      }
    

    方法里面主要就是执行了 runWrapped 方法

      private void runWrapped() {
        switch (runReason) {
          case INITIALIZE:
            stage = getNextStage(Stage.INITIALIZE);
            currentGenerator = getNextGenerator();
            runGenerators();
            break;
          case SWITCH_TO_SOURCE_SERVICE:
            ...
            break;
          case DECODE_DATA:
            ...
            break;
          ...
        }
      }
    

    runReason在DecodeJob.init方法中被初始化为INITIALIZE,所以我们需要关注的的代码为

    // 获取下一个状态RESOURCE_CACHE并赋值给stage
    stage = getNextStage(Stage.INITIALIZE);
    // getNextGenerator()返回的是 ResourceCacheGenerator
    currentGenerator = getNextGenerator();
    runGenerators();
    
      private Stage getNextStage(Stage current) {
        switch (current) {
          case INITIALIZE:
            return diskCacheStrategy.decodeCachedResource()
                ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
          case RESOURCE_CACHE:
            ...
          case DATA_CACHE:
            ...
          case SOURCE:
          case FINISHED:
            ...
          ...
        }
      }
      
      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);
        }
      }
    

    stage 的状态被修改为 RESOURCE_CACHE,currentGenerator 为 ResourceCacheGenerator,继续跟进 runGenerators 方法:

      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;
          }
        }
        // We've run out of stages and generators, give up.
        if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
          notifyFailed();
        }
    
      }
    

    该方法中会依次调用各个状态生成的 DataFetcherGenerator 的 startNext() 尝试fetch数据,取数据成功了该方法就结束。若状态到了Stage.FINISHED 或 job 被取消,且所有状态的DataFetcherGenerator.startNext()都无法满足条件,则调用SingleRequest.onLoadFailed进行错误处理。根据getNextGenerator()方法代码可发现:DataFetcherGenerator 有三个子类:

    • ResourceCacheGenerator
      获取downsample、transform后的资源文件的缓存文件

    • DataCacheGenerator
      获取原始的没有修改过的资源文件的缓存文件

    • SourceGenerator
      获取原始源数据

    先跟进下 ResourceCacheGenerator.startNext:

    @Override
      public boolean startNext() {
        // list里面只有一个GlideUrl对象
        List<Key> sourceIds = helper.getCacheKeys();
        if (sourceIds.isEmpty()) {
          return false;
        }
        // 获得了三个可以到达的registeredResourceClasses
        // GifDrawable、Bitmap、BitmapDrawable
        List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
        if (resourceClasses.isEmpty()) {
          if (File.class.equals(helper.getTranscodeClass())) {
            return false;
          }
          throw new IllegalStateException(
             "Failed to find any load path from " + helper.getModelClass() + " to "
                 + helper.getTranscodeClass());
        }
        
        // 遍历sourceIds中的每一个key、resourceClasses中每一个class,以及其他的一些值组成key
        // 尝试在磁盘缓存中以key找到缓存文件
        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);
          
          // 如果找到了缓存文件,循环条件则会为false,退出循环
          if (cacheFile != null) {
            sourceKey = sourceId;
            // 1. 找出注入时以File.class为modelClass的注入代码
            // 2. 调用所有注入的factory.build方法得到ModelLoader
            // 3 .过滤掉不可能处理model的ModelLoader
            // 此时的modelLoaders值为:
            // [ByteBufferFileLoader, FileLoader, FileLoader, UnitModelLoader]
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
          }
        }
    
        // 如果找到了缓存文件,hasNextModelLoader()方法则会为true,可以执行循环
        // 没有找到缓存文件,则不会进入循环,会直接返回false
        loadData = null;
        boolean started = false;
        while (!started && hasNextModelLoader()) {
          ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
          // 在循环中会依次判断某个ModelLoader能不能加载此文件
          loadData = modelLoader.buildLoadData(cacheFile,
              helper.getWidth(), helper.getHeight(), helper.getOptions());
          if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
            started = true;
            
            // 如果某个ModelLoader可以,那么就调用其fetcher进行加载数据
            // 加载成功或失败会通知自身
            loadData.fetcher.loadData(helper.getPriority(), this);
          }
        }
    
        return started;
      }
    

    如果已经找到一个一条可以加载的路径,那么就调用此fetcher.loadData方法进行加载。同时,该方法ResourceCacheGenerator.startNext返回true,这就意味着DecodeJob无需在尝试另外的 DataFetcherGenerator 进行加载,整个into过程已经大致完成,剩下的就是等待资源加载完毕后触发回调。续分析 loadData.fetcher.loadData(helper.getPriority(), this),这里的 fetcher 是 ByteBufferFetcher:

        // ByteBufferFetcher
        @Override
        public void loadData(@NonNull Priority priority,
            @NonNull DataCallback<? super ByteBuffer> callback) {
          ByteBuffer result;
          try {
            // 这里的file就是缓存下来的source file
            result = ByteBufferUtil.fromFile(file);
          } catch (IOException e) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
              Log.d(TAG, "Failed to obtain ByteBuffer for file", e);
            }
            callback.onLoadFailed(e);
            return;
          }
    
          callback.onDataReady(result);
        }
    

    ByteBufferUtil.fromFile使用了RandomAccessFile和FileChannel进行文件操作。如果操作失败,调用callback.onLoadFailed(e)通知ResourceCacheGenerator类,该类会将操作转发给DecodeJob;callback.onDataReady操作类似。这样程序就回到了DecodeJob回调方法中了。

    但是按照我们的流程,第一次加载时没有缓存的,所以 ResourceCacheGenerator.startNext 中找不到缓存文件,继续交给DataCacheGenerator.startNext 处理:

    public boolean startNext() {
        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;
      }
    

    由于第一次加载,本地缓存没有,接着交给最后一个 SourceGenerator.startNext 来处理

    @Override
      public boolean startNext() {
      
        // 首次运行dataToCache为null
        if (dataToCache != null) {
          Object data = dataToCache;
          dataToCache = null;
          cacheData(data);
        }
    
        // 首次运行sourceCacheGenerator为null
        if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
          return true;
        }
        sourceCacheGenerator = null;
    
        loadData = null;
        boolean started = false;
        while (!started && hasNextModelLoader()) {
          loadData = helper.getLoadData().get(loadDataListIndex++);
          if (loadData != null
              && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
            started = true;
            loadData.fetcher.loadData(helper.getPriority(), this);
          }
        }
        return started;
      }
    

    helper.getLoadData()的值在ResourceCacheGenerator中就已经被获取并缓存下来了,这是一个MultiModelLoader对象生成的LoadData对象,LoadData对象里面有两个fetcher。

    遍历LoadData list,找出符合条件的LoadData,然后调用loadData.fetcher.loadData加载数据。若loadData不为null,会判断Glide的缓存策略是否可以缓存此数据源,或者是否有加载路径。MultiModelLoader里面的fetcher是MultiFetcher,我们来看下MultiFetcher.loadData:

        // MultiFetcher
        @Override
        public void loadData(
            @NonNull Priority priority, @NonNull DataCallback<? super Data> callback) {
          this.priority = priority;
          this.callback = callback;
          exceptions = throwableListPool.acquire();
          // 类型是HttpUrlFetcher
          fetchers.get(currentIndex).loadData(priority, this);
    
          if (isCancelled) {
            cancel();
          }
        }
    

    继续跟进 HttpUrlFetcher.loadData

      // HttpUrlFetcher
      @Override
      public void loadData(@NonNull Priority priority,
          @NonNull DataCallback<? super InputStream> callback) {
        long startTime = LogTime.getLogTime();
        try {
          InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
          callback.onDataReady(result);
        } catch (IOException e) {
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Failed to load data for url", e);
          }
          callback.onLoadFailed(e);
        } finally {
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
          }
        }
      }
    

    这里将请求操作放到了loadDataWithRedirects方法中,然后将请求结果通过回调返回上一层也就是MultiFetcher中。跟进HttpUrlFetcher.loadDataWithRedirects:

    // HttpUrlFetcher
    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) {
            // Do nothing, this is best effort.
          }
        }
    
        // connectionFactory默认是DefaultHttpUrlConnectionFactory
        // 其build方法就是调用了url.openConnection()
        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);
    
        // 禁止HttpUrlConnection自动重定向,重定向功能由本方法自己实现
        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)) {
          // statusCode=2xx,请求成功
          return getStreamForSuccessfulRequest(urlConnection);
        } else if (isHttpRedirect(statusCode)) {
          // statusCode=3xx,需要重定向
          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) {
          // -1 表示不是HTTP响应
          throw new HttpException(statusCode);
        } else {
          throw new HttpException(urlConnection.getResponseMessage(), statusCode);
        }
      }
      
    private static boolean isHttpOk(int statusCode) {
      return statusCode / 100 == 2;
    }
    
    private static boolean isHttpRedirect(int statusCode) {
      return statusCode / 100 == 3;
    }
    

    现在我们已经获得网络图片的InputStream了,该资源会通过回调经过MultiFetcher到达SourceGenerator中。看下DataCallback回调在SourceGenerator中的实现:

      // 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);
        }
      }
    
      @Override
      public void onLoadFailed(@NonNull Exception e) {
        cb.onDataFetcherFailed(originalKey, e, loadData.fetcher, loadData.fetcher.getDataSource());
      }
    

    onDataReady方法会首先判data能不能缓存,若能缓存则缓存起来,然后调用DataCacheGenerator进行加载缓存;若不能缓存,则直接调用DecodeJob.onDataFetcherReady方法通知外界data已经准备好了。继续跟进
    DecodeJob.onDataFetcherReady:

      // DecodeJob
      @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();
          }
        }
      }
    

    确认执行线程后调用decodeFromRetrievedData()方法进行解码:

      // DecodeJob
      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 {
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
        } catch (GlideException e) {
          e.setLoggingDetails(currentAttemptingKey, currentDataSource);
          throwables.add(e);
        }
        if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
    

    先调用decodeFromData方法进行解码,然后调用notifyEncodeAndRelease方法进行缓存,同时也会通知EngineJob资源已经准备好了,先看decodeFromData:

      // DecodeJob
      private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
          DataSource dataSource) throws GlideException {
        try {
          if (data == null) {
            return null;
          }
          long startTime = LogTime.getLogTime();
          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);
      }
    

    decodeFromData方法内部又会调用decodeFromFetcher,在decodeFromFetcher方法中首先会获取LoadPath。然后调用runLoadPath方法解析成资源:

    // DecodeJob
    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 {
        // ResourceType in DecodeCallback below is required for compilation to work with gradle.
        return path.load(
            rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
      } finally {
        rewinder.cleanup();
      }
    }
    
    

    注意runLoadPath方法使用到了DataRewinder,这是一个将数据流里面的指针重新指向开头的类,在调用ResourceDecoder对data进行编码时会尝试很多个编码器,所以每一次尝试后都需要重置索引。在path.load(rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource))这行代码中,最后传入了一个DecodeCallback回调,该类的回调方法会回调给DecodeJob对应的方法:

    private final class DecodeCallback<Z> implements DecodePath.DecodeCallback<Z> {
    
      private final DataSource dataSource;
    
      @Synthetic
      DecodeCallback(DataSource dataSource) {
        this.dataSource = dataSource;
      }
    
      @NonNull
      @Override
      public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
        return DecodeJob.this.onResourceDecoded(dataSource, decoded);
      }
    }
    

    继续跟进LoadPath.load

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

    主要调用了loadWithExceptionList方法

    // LoadPath
    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;
        //noinspection ForLoopReplaceableByForEach to improve perf
        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,都调用其decode方法,直到有一个DecodePath可以decode出资源。继续跟进DecodePath.decode:

      // DecodePath
      public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
          @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
        // 使用ResourceDecoder List进行decode
        Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
        // 将decoded的资源进行transform
        Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
        // 将transformed的资源进行transcode
        return transcoder.transcode(transformed, options);
      }
    

    先看一下DecodePath.decodeResource

      @NonNull
      private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
          int height, @NonNull Options options) throws GlideException {
        List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
        try {
          return decodeResourceWithList(rewinder, width, height, options, exceptions);
        } finally {
          listPool.release(exceptions);
        }
      }
    

    继续跟进DecodePath.decodeResourceWithList

    @NonNull
      private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
          int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
        Resource<ResourceType> result = null;
        
        // decoders只有一条,就是ByteBufferBitmapDecoder
        for (int i = 0, size = decoders.size(); i < size; i++) {
          ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
          try {
          
            // rewinder是ByteBufferRewind类型
            // data为ByteBuffer类型
            DataType data = rewinder.rewindAndGet();
            if (decoder.handles(data, options)) {
              // 调用ByteBuffer.position(0)复位
              data = rewinder.rewindAndGet();
              // 开始解码
              result = decoder.decode(data, width, height, options);
            }
           
          } catch (IOException | RuntimeException | OutOfMemoryError e) {
            ...
          }
    
          if (result != null) {
            break;
          }
        }
        ...
        return result;
      }
    

    继续跟进ByteBufferBitmapDecoder.decode方法

      @Override
      public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
          @NonNull Options options)
          throws IOException {
        InputStream is = ByteBufferUtil.toStream(source);
        return downsampler.decode(is, width, height, options);
      }
    

    先将ByteBuffer转换成InputStream,然后在调用Downsampler.decode方法进行解码。回到DecodePath.decode,解码后调用callback.onResourceDecoded(decoded);,DecodeJob中的DecodeCallback实现了DecodePath.DecodeCallback的onResourceDecoded方法,该方法里面调用了DecodeJob.onResourceDecoded(dataSource, decoded):

    // DecodeJob
    <Z> Resource<Z> onResourceDecoded(DataSource dataSource,
          @NonNull Resource<Z> decoded) {
    
        Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
        Transformation<Z> appliedTransformation = null;
        Resource<Z> transformed = decoded;
        
        // dataSource为DATA_DISK_CACHE,所以满足条件
        if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
          appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
          transformed = appliedTransformation.transform(glideContext, decoded, width, height);
        }
        
        ...
    
        final EncodeStrategy encodeStrategy;
        final ResourceEncoder<Z> encoder;
        // Bitmap有注册对应的BitmapEncoder,所以是available的
        if (decodeHelper.isResourceEncoderAvailable(transformed)) {
          // encoder就是BitmapEncoder
          encoder = decodeHelper.getResultEncoder(transformed);
          // encodeStrategy为EncodeStrategy.TRANSFORMED
          encodeStrategy = encoder.getEncodeStrategy(options);
        } else {
          encoder = null;
          encodeStrategy = EncodeStrategy.NONE;
        }
    
        Resource<Z> result = transformed;
        
        ...
    
        return result;
      }
    

    继续回到DecodePath.decode方法中的transcoder.transcode(transformed, options);
    这里的transcoder就是BitmapDrawableTranscoder,该方法返回了一个LazyBitmapDrawableResource。至此,资源已经解码完毕。然后我们继续回到 DecodeJob.decodeFromRetrievedData方法中:

    // DecodeJob
    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 {
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
        } catch (GlideException e) {
          e.setLoggingDetails(currentAttemptingKey, currentDataSource);
          throwables.add(e);
        }
        if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
    

    拿到 resource 之后会调用notifyEncodeAndRelease(resource, currentDataSource);,跟进 DecodeJob.notifyEncodeAndRelease:

    // DecodeJob
    private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    
        // resource是BitmapResource类型,实现了Initializable接口
        if (resource instanceof Initializable) {
          // initialize方法调用了bitmap.prepareToDraw()
          ((Initializable) resource).initialize();
        }
    
        Resource<R> result = resource;
        ...
    
        // 通知回调,资源已经就绪
        notifyComplete(result, dataSource);
    
        ...
        
        // 进行清理工作
        onEncodeComplete();
      }
    
    

    notifyComplete方法中该方法内部会调用callback.onResourceReady(resource, dataSource)将结果传递给回调,这里的回调是EngineJob:

    // EngineJob
      @Override
      public void onResourceReady(Resource<R> resource, DataSource dataSource) {
        synchronized (this) {
          this.resource = resource;
          this.dataSource = dataSource;
        }
        notifyCallbacksOfResult();
      }
    

    这里存储资源后继续调用EngineJob.notifyCallbacksOfResult

    // EngineJob
    @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");
          }
          
          // new EngineResource<>(resource, isMemoryCacheable, /*isRecyclable=*/ true)
          engineResource = engineResourceFactory.build(resource, isCacheable);
         
          hasResource = true;
          copy = cbs.copy();
          incrementPendingCallbacks(copy.size() + 1);
    
          localKey = key;
          localResource = engineResource;
        }
    
        // listener就是Engine,该方法会将资源保存到activeResources中
        listener.onEngineJobComplete(this, localKey, localResource);
    
        // 这里的ResourceCallbackAndExecutor就是之前创建EngineJob和DecodeJob时并在执行DecodeJob之前添加的回调
        // entry.executor就是Glide.with.load.into中出现的Executors.mainThreadExecutor()
        // entry.cb就是SingleRequest
        for (final ResourceCallbackAndExecutor entry : copy) {
          entry.executor.execute(new CallResourceReady(entry.cb));
        }
        decrementPendingCallbacks();
      }
    

    先来看下listener.onEngineJobComplete(this, localKey, localResource),listener就是Engine,跟进Engine.onEngineJobComplete:

      // Engine
      @Override
      public synchronized void onEngineJobComplete(
          EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
        
        // 设置资源的回调为自己,这样在资源释放时会通知自己的回调方法
        if (resource != null) {
          resource.setResourceListener(key, this);
    
          // 将资源放入activeResources中,资源变为active状态
          if (resource.isCacheable()) {
            activeResources.activate(key, resource);
          }
        }
    
        // 将engineJob从Jobs中移除
        jobs.removeIfCurrent(key, engineJob);
      }
    

    再回到EngineJob.notifyCallbacksOfResult,看下entry.executor.execute(new CallResourceReady(entry.cb)),entry.executor就是Glide.with.load.into中出现的Executors.mainThreadExecutor(),内部使用MainLooper的Handler,在execute Runnable时使用此Handler post出去,这里entry.cb就是SingleRequest,所以我们要看下CallResourceReady:

      // EngineJob
      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();
              // 调用callback
              callCallbackOnResourceReady(cb);
              // 移除callback
              removeCallback(cb);
            }
            decrementPendingCallbacks();
          }
        }
      }
    

    跟进EngineJob.callCallbackOnResourceReady

      // EngineJob
      @Synthetic
      synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
        try {
          // 调用SingleRequest.onResourceReady
          cb.onResourceReady(engineResource, dataSource);
        } catch (Throwable t) {
          throw new CallbackException(t);
        }
      }
    

    继续跟进SingleRequest.onResourceReady

    // SingleRequest
    @Override
      public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
        stateVerifier.throwIfRecycled();
        loadStatus = null;
        if (resource == null) {
          ...
          onLoadFailed(exception);
          return;
        }
    
        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          releaseResource(resource);
          ...
          onLoadFailed(exception);
          return;
        }
    
        ...
    
        onResourceReady((Resource<R>) resource, (R) received, dataSource);
      }
    

    这里进行一些资源的判空处理,然后调用onResourceReady((Resource<R>) resource, (R) received, dataSource);

    // SingleRequest
    private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
        // We must call isFirstReadyResource before setting status.
        
        // 由于requestCoordinator为null,所以返回true
        boolean isFirstResource = isFirstReadyResource();
        // 将status状态设置为COMPLETE
        status = Status.COMPLETE;
        this.resource = resource;
    
        ...
    
        isCallingCallbacks = true;
        try {
          // 尝试调用各个listener的onResourceReady回调进行处理
          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为DrawableImageViewTarget
            target.onResourceReady(result, animation);
          }
        } finally {
          isCallingCallbacks = false;
        }
    
        notifyLoadSuccess();
      }
    

    DrawableImageViewTarget的基类ImageViewTarget实现了onResourceReady(result, animation)方法:

      // ImageViewTarget
      @Override
      public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
        // NO_ANIMATION.transition返回false
        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);
    

    setResource 方法由 DrawableImageViewTarget 实现

      // DrawableImageViewTarget
      @Override
      protected void setResource(@Nullable Drawable resource) {
        // view 是 ImageView 类型
        view.setImageDrawable(resource);
      }
    

    至此为止,Glide.with(this).load(url).into(imageView)已经将网络图片正确展示在ImageView上。

    总结

    Glide.with(this).load(url).into(imageView)整个源码调用时序图如下:

    参考链接
    https://muyangmin.github.io/glide-docs-cn/
    https://blog.yorek.xyz/android/3rd-library/glide2/

    相关文章

      网友评论

          本文标题:Glide源码分析-网络图片加载主流程分析

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