掌握Glide(1) : 从源码看,Glide的执行流程

Glide最简单、标准的用法如下:

Glide.with(this)          //第一步 (返回RequestManager对象)
     .load(url)           //第二步 (返回Y extends Target对象,主要是设置model这个属性)
     .into(imageView);    //第三步

本文,将根据Glide加载的with、load、into 这三个步骤从源码进入学习,如无特殊说明,源码版本均指:4.6.1

一.with()

with()方法是Glide类中的一组静态方法,它有好几个方法重载,我们来看一下Glide类中所有with()方法的方法重载:

#Glide.class

  @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 android.app.Fragment fragment) {
     
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  @NonNull
  public static RequestManager with(@NonNull Fragment fragment) {
     
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  @NonNull
  public static RequestManager with(@NonNull View view) {
     
    return getRetriever(view.getContext()).get(view);
  }

可以看到,with()方法的重载种类非常多,既可以传入Activity,也可以传入Fragment或者是Context,甚至View。每一个with()方法重载的代码都非常简单,都是先调用RequestManagerRetriever的静态get()方法得到一个RequestManagerRetriever对象,这个静态get()方法就是一个单例实现。然后再调用RequestManagerRetriever的实例get()方法,去获取RequestManager对象。

public class RequestManagerRetriever implements Handler.Callback {
     

  .....
  /**
   * The top application level RequestManager.
   */
  private volatile RequestManager applicationManager;

  /**
   * Pending adds for RequestManagerFragments.
   */
  @VisibleForTesting
  final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
      new HashMap<>();

  /**
   * Pending adds for SupportRequestManagerFragments.
   */
  @VisibleForTesting
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();

  /**
   * Main thread handler to handle cleaning up pending fragment maps.
   */
  private final Handler handler;
  private final RequestManagerFactory factory;

 
  @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, null /*parentHint*/);
    }
  }

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

  @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, null /*parentHint*/);
    }
  }

  @NonNull
  public RequestManager get(@NonNull View view) {
     
    if (Util.isOnBackgroundThread()) {
     
      return get(view.getContext().getApplicationContext());
    }

    Preconditions.checkNotNull(view);
    Preconditions.checkNotNull(view.getContext(),
        "Unable to obtain a request manager for a view without a Context");
    Activity activity = findActivity(view.getContext());
    // The view might be somewhere else, like a service.
    if (activity == null) {
     
      return get(view.getContext().getApplicationContext());
    }

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

  @NonNull
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
  public RequestManager get(@NonNull android.app.Fragment fragment) {
     
    if (fragment.getActivity() == null) {
     
      throw new IllegalArgumentException(
          "You cannot start a load on a fragment before it is attached");
    }
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
     
      return get(fragment.getActivity().getApplicationContext());
    } else {
     
      android.app.FragmentManager fm = fragment.getChildFragmentManager();
      return fragmentGet(fragment.getActivity(), fm, fragment);
    }
  }


  private static void findAllSupportFragmentsWithViews(
      @Nullable Collection<Fragment> topLevelFragments,
      @NonNull Map<View, Fragment> result) {
     
    if (topLevelFragments == null) {
     
      return;
    }
    for (Fragment fragment : topLevelFragments) {
     
      // getFragment()s in the support FragmentManager may contain null values, see #1991.
      if (fragment == null || fragment.getView() == null) {
     
        continue;
      }
      result.put(fragment.getView(), fragment);
      findAllSupportFragmentsWithViews(fragment.getChildFragmentManager().getFragments(), result);
    }
  }

  @Nullable
  private Fragment findSupportFragment(@NonNull View target, @NonNull FragmentActivity activity) {
     
    tempViewToSupportFragment.clear();
    findAllSupportFragmentsWithViews(
        activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
    Fragment result = null;
    View activityRoot = activity.findViewById(android.R.id.content);
    View current = target;
    while (!current.equals(activityRoot)) {
     
      result = tempViewToSupportFragment.get(current);
      if (result != null) {
     
        break;
      }
      if (current.getParent() instanceof View) {
     
        current = (View) current.getParent();
      } else {
     
        break;
      }
    }

    tempViewToSupportFragment.clear();
    return result;
  }

  @Nullable
  private android.app.Fragment findFragment(@NonNull View target, @NonNull Activity activity) {
     
    tempViewToFragment.clear();
    findAllFragmentsWithViews(activity.getFragmentManager(), tempViewToFragment);

    android.app.Fragment result = null;

    View activityRoot = activity.findViewById(android.R.id.content);
    View current = target;
    while (!current.equals(activityRoot)) {
     
      result = tempViewToFragment.get(current);
      if (result != null) {
     
        break;
      }
      if (current.getParent() instanceof View) {
     
        current = (View) current.getParent();
      } else {
     
        break;
      }
    }
    tempViewToFragment.clear();
    return result;
  }

  @TargetApi(Build.VERSION_CODES.O)
  private void findAllFragmentsWithViews(
      @NonNull android.app.FragmentManager fragmentManager,
      @NonNull ArrayMap<View, android.app.Fragment> result) {
     
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     
      for (android.app.Fragment fragment : fragmentManager.getFragments()) {
     
        if (fragment.getView() != null) {
     
          result.put(fragment.getView(), fragment);
          findAllFragmentsWithViews(fragment.getChildFragmentManager(), result);
        }
      }
    } else {
     
      findAllFragmentsWithViewsPreO(fragmentManager, result);
    }
  }

  private void findAllFragmentsWithViewsPreO(
      @NonNull android.app.FragmentManager fragmentManager,
      @NonNull ArrayMap<View, android.app.Fragment> result) {
     
    int index = 0;
    while (true) {
     
      tempBundle.putInt(FRAGMENT_INDEX_KEY, index++);
      android.app.Fragment fragment = null;
      try {
     
        fragment = fragmentManager.getFragment(tempBundle, FRAGMENT_INDEX_KEY);
      } catch (Exception e) {
     
        // This generates log spam from FragmentManager anyway.
      }
      if (fragment == null) {
     
        break;
      }
      if (fragment.getView() != null) {
     
        result.put(fragment.getView(), fragment);
        if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
     
          findAllFragmentsWithViews(fragment.getChildFragmentManager(), result);
        }
      }
    }
  }

  @Nullable
  private Activity findActivity(@NonNull Context context) {
     
    if (context instanceof Activity) {
     
      return (Activity) context;
    } else if (context instanceof ContextWrapper) {
     
      return findActivity(((ContextWrapper) context).getBaseContext());
    } else {
     
      return null;
    }
  }

 
  @NonNull
  private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint) {
     
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    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;
  }


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


 @NonNull
  RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
     
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
     
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        pendingRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

  @NonNull
  SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
     
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
     
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

 

  .......
}

上面代码的位置,进行了适当调准。

代码虽然比较多,但逻辑很清晰。

RequestManagerRetriever类中看似有很多个get()方法的重载,什么Context参数,Activity参数,Fragment参数等等,实际上只有两种情况而已,即传入Application类型的参数,和传入非Application类型的参数。

另外,如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理。

关于这部分细节,在掌握Glide(2) : 从源码看,Glide是如何关联生命周期的 已经在这篇文章中有详细介绍,本文只针对Glide的主流程。

回到主题,with()方法其实就是为了得到一个RequestManager对象而已,然后Glide会根据我们传入with()方法的参数来确定图片加载的生命周期。

二.load()

从一中可知, Glide.with() 返回的是 RequestManager. 因此 Glide.with().into() 的源码,直接到RequestManager.class 中查找.

  # RequestManager.class
  
  @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(@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);
  }

和with() 方法一样, load()方法也是有多种重载, 包括Bitmap 、Drawable、String 、Uri、File等多种类型。但发现它们都是调用 asDrawable() 的load,并将 load()方法中的参数以model传递。我们看一下 asDrawable()方法:

  # RequestManager.class
  
  @NonNull
  @CheckResult
  public RequestBuilder<Drawable> asDrawable() {
     
    return as(Drawable.class);
  }


 @NonNull
  @CheckResult
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
     
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

可以看到,asDrawable()方法最后以 new 一个RequestBuilder 对象返回。

也就是说,asDrawable().load( ) 转入到 RequestBuilder .class 中的 load( )

 # RequestBuilder.class
 
  @NonNull
  @CheckResult
  @SuppressWarnings("unchecked")
  @Override
  public RequestBuilder<TranscodeType> load(@Nullable Object model) {
     
    return loadGeneric(model);
  }

  @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
     
    this.model = model;
    isModelSet = true;
    return this;
  }

可以发现,load()方法只是设置了model这个属性的值
至此,load(url)方法全部结束。

三. into()

从二中可知,into()方法同样在 RequestBuilder .class 中。

# RequestBuilder.class

代码片1

 @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.
      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(       ---分析1A
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,requestOptions);    ---分析1B
  }

在上面代码第39行中,需要分为2部分进行分析,1A、1B,即
一是 into () 方法
二是 into()方法里面的

glideContext.buildImageViewTarget(view, transcodeClass),/*targetListener=*/ null,requestOptions

1. 1A分析

# RequestBuilder.class

代码片2

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
     
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
     
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    Request request = buildRequest(target, targetListener, options);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(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;
    }

    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

第18行代码,获取此时是否有正在进行的Request请求,如果有,则进行逻辑判断,决定是否需要开启一个新的,还是复用之前的。如果没有,进行第19行代码的if循环中。

我们跳转if判断,先分析第36、37行代码。

点击第36行代码,发现跳转到 Target.class 的 setRequest方法中。但是,Target却是一个接口。需要找到它的实现类。

查看 Target的实现类你会发现,里面错综复杂。似乎陷入了不知所措的局面。

但你如果细看代码片2的第5行、6行代码就会发现,此方法中的target 类型是T。而整个代码片2的返回类型也是T。

但代码片1的返回类型是ViewTarget。 代码片1的第39行代码into方法专递到代码片2就是T类型。

换句话说,这里的T,就是 ViewTarget。

上面几段话有点饶,需要你根据return 细细琢磨一下。

通过 ViewTarget into = Glide.with(MainActivity.this).load(url) 也是可以验证出来的。

掌握Glide(1) : 从源码看,Glide的执行流程_第1张图片
掌握Glide(1) : 从源码看,Glide的执行流程_第2张图片

我们继续看 target.setRequest(request); 直接进入 ViewTarget.class方法中

2.ViewTarget类

# ViewTarget.class

@Override
  public void setRequest(@Nullable Request request) {
     
    setTag(request);
  }

private void setTag(@Nullable Object tag) {
     
    if (tagId == null) {
     
      isTagUsedAtLeastOnce = true;
      view.setTag(tag);
    } else {
     
      view.setTag(tagId, tag);
    }
  }

其实就是将Request和View做了一个绑定的关系,保存在View的tag之中。这步设置完成之后,就进入到了最后一步。track当前请求。即代码片2第37行代码:

#RequestManager.class

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

TargetTracker和RequestTracker分别是对target和request做了一个管理。
TargetTracker类中更加简单,有点类似一个扩展的List结构,也就是保存了由当前RequestManager在处理的所有Target的集合。
而RequestTracker则是所有Request的集合,代码如下:


代码片3 
# RequestTracker.class

public void runRequest(@NonNull Request request) {
     
    requests.add(request);
    if (!isPaused) {
     
      request.begin();
    } else {
     
      pendingRequests.add(request);
    }
  }

这个方法中,分为两种情况,isPaused变量标识界面是否处于onStop状态,如果此时还可见,则直接调用request#begin方法执行,否则则是加入到pendingRequests中,这里pendingRequests的作用仅仅是为了保证Request不被Gc,因为requests是一个WeakHashMap,如果不使用pendingRequests强引用缓存,那么这个请求就有可能被回收掉,这里是做了这样一个处理,就能保证这些request不被系统回收掉,同时在requests也一定存在。下面我们继续分析begin这个方法。

下面我们继续分析begin这个方法。

3. begin()方法

点击代码片3第8行代码的begin()方法,发现跳到Request.class 中。但Request却是一个接口。必须找到它的实现类才行。

我们看一下Resuest的实现类,如下:
掌握Glide(1) : 从源码看,Glide的执行流程_第3张图片
通过三个实现类的命名,我们很容易猜测到 代码片3第8行代码的begin()方法中,Request类的实现类是SingleRequest。

但这里只是猜测。我们需要去验证我们的猜测。(这也是阅读源码很重要的一种思路与技巧)

其实request的初始化位置,在代码片2第16行,再次贴出代码片2。

# RequestBuilder.class

代码片2

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
     
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
     
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    Request request = buildRequest(target, targetListener, options);
    
    .....(较前面的代码片2,删除部分代码)
    
    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

我们看一下16行代码的buildRequest方法:


# RequestBuilder.class

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

我们接着看上面代码第8行代码:

# RequestBuilder.class

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 mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions);

    if (errorRequestCoordinator == null) {
     
      return mainRequest;
    }

    .....

    Request errorRequest = errorBuilder.buildRequestRecursive(
        target,
        targetListener,
        errorRequestCoordinator,
        errorBuilder.transitionOptions,
        errorBuilder.requestOptions.getPriority(),
        errorOverrideWidth,
        errorOverrideHeight,
        errorBuilder.requestOptions);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }

从这里开始,ThumbnailRequestCoordinator、ErrorRequestCoordinator、SingleRequest 其实都出现了。
代码的主思路还是很清晰,分别是 缩略图请求协助类、错误请求协助类、正常的请求类。他们的英文命名,也的确如此。关于这部分细节,大家可以从上述代码片开始。(都在RequestBuilder.class)。

这部分不是Glide执行流程的主流程,我们直接告诉结论:这里request的实现类是SingleRequest类。

4. SingleRequest类

回到代码片3第8行代码,即:


代码片3 
# RequestTracker.class

public void runRequest(@NonNull Request request) {
     
    requests.add(request);
    if (!isPaused) {
     
      request.begin();
    } else {
     
      pendingRequests.add(request);
    }
  }

request.begin 也就是调用 SingleRequest类中的begin方法:


代码片4

# SingleRequest.class 

@Override
  public void begin() {
     
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    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.

    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进行判断,这个model此时就是我们传的那个url,如果为空,则直接load失败,然后是一些状态的检查和一些回调方法等,接下来判断size,如果是有效的,则触发去真正的请求,否则则是设置一个回调,等待view布局有size之后,再来触发请求,真正的请求其实就在onSizeReady中被得到执行。

这个方法中,首先检查状态是不是在等待size,如果不是,则表明size已经有了,下面则是更新状态到Status.RUNNING,进而去调用Engine根据参数,这里面包含了所有的参数信息,缓存,图片显示等等,然后去开始真正请求,网络、内存、磁盘缓存等等。这块的东西很复杂,暂且放一放,这块设计到一个结果的回调。

SingleRequest类有一个接口,ResourceCallback

public interface ResourceCallback {
     

  /**
   * Called when a resource is successfully loaded.
   *
   * @param resource The loaded resource.
   */
  void onResourceReady(Resource<?> resource, DataSource dataSource);

  /**
   * Called when a resource fails to load successfully.
   *
   * @param e a non-null {@link GlideException}.
   */
  void onLoadFailed(GlideException e);
}

实现是在SignleRequest中,具体代码大家可自行分析,显然,必须要做的一件事情是告诉Target此时的加载结果,再由Target去通知View做如何的展示,实际上,也是这样子实现的。具体细节这里不展开了。

我们还是回到begin方法。在代码片4第22行代码,我们看到了 target.onLoadStarted(getPlaceholderDrawable())

这里的onLoadStarted还是接口类 Target中的方法。在 第三部分 1A部分,我们分析了这里的 target对应的是ViewTarget实现类。我们直接在ViewTarget.class中找onLoadStarted方法。如下:


# ViewTarget.class

  @CallSuper
  @Override
  public void onLoadStarted(@Nullable Drawable placeholder) {
     
    super.onLoadStarted(placeholder);
    maybeAddAttachStateListener();
  }

第7行代码super方法跳转到父类,是一个空实现的方法。
第8行代码,是状态监听的方法。

又没找到我们想要的。

这时候,就涉及到代码片1B的分析了。

5. 1B的分析

代码片1中1B的代码如下:

glideContext.buildImageViewTarget(view, transcodeClass),/*targetListener=*/ null,requestOptions

对应的代码分别如下:


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

#ImageViewTargetFactory.class

public class 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)) {
     
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
     
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
}

在load()方法中的 as传递的是 Drawable.class 即,这里执行上述代码第19、20行代码,

也就是说返回DrawableImageViewTarget类。
掌握Glide(1) : 从源码看,Glide的执行流程_第4张图片
ImageViewTarget.class中onLoadStarted方法如下

# ImageViewTarget.class

 @Override
  public void onLoadStarted(@Nullable Drawable placeholder) {
     
    super.onLoadStarted(placeholder);
    setResourceInternal(null);
    setDrawable(placeholder);
  }

 @Override
  public void setDrawable(Drawable drawable) {
     
    view.setImageDrawable(drawable);
  }

这个方法的实现很简单,就是为view提前设置一些状态,比如placeholder信息等等,然后等待Engine后续的加载完成。

至此,这一块简单的流程就已经介绍结束,基本的加载流程和LifiCircle的东西想必有了一个初步的认识,从文章分析来看,最复杂的部分可能就是Engine根据参数来具体加载的过程了,后续继续分析。

在上述第12行代码中,加载出图片。在此,ImageView上面就已经能够正常的显示出图片了。

至此,Glide的执行流程,分析完毕。

你可能感兴趣的:(Android主流框架)