Glide源码分析

版本号:4.9.0

一.基本概念

1.Model

数据来源,不管是imgURL、资源文件还是本地文件,在Glide中封装为Model

2.Data

原始数据,获取Model之后,处理成原始数据,一般就是输入流,在Glide中封装为Data

3.Resource

解码之后的资源,比如将输入流解码成Bitmap

4.TransformedResource

Resource变换之后的资源,比如:裁剪。

5.TranscodedResource

转码之后的资源,将解码之后的资源转换成统一的格式。

5.Target

图片显示的目标。

加载流程

二.基本使用

Glide.with(this)
    .load(imgUrl)
    .placeholder(R.mipmap.ic_launcher)
    .error(R.mipmap.ic_launcher)
    .override(300,300)//指定图片的尺寸
    .skipMemoryCache(true)//不使用内存缓存
    .diskCacheStrategy(DiskCacheStrategy.ALL)//磁盘缓存:缓存所有版本的
    .centerCrop() //设置缩放类型
    .priority(Priority.HIGH)//指定优先级,尽可能处理优先级高的
    .into(imageView)

最核心的方法其实就是:with()、load()、into(),创建请求对象,指定数据源,设置显示目标。其他的方法都是一些图片的设置和缓存设置等。下面分别来看一下这三个方法:

1.with()方法

该方法有很多的重载,传入的参数分别是context、activity、fragmentActivity、fragment,下面以参数为context的方法为为例分析:

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

with()方法返回一个RequestManager对象,该对象是请求管理的对象,是通过RequestManagerRetrieverget()方法获取的,RequestManagerRetriever就是用来生产RequestManager对象的。下面看一下get()方法:

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

如果不是在UI线程或者context是Application,就会调用getApplicationManager(context);方法,否则就会对context分类调用对应的方法。getApplicationManager(context);方法就是通过Glide创建一个RequestManager对象。

下面看一下参数为activity的方法:

public class RequestManagerRetriever implements Handler.Callback{
    @SuppressWarnings("deprecation")
    @NonNull
    public RequestManager get(@NonNull Activity activity) {
        if (Util.isOnBackgroundThread()) {
          //如果是在子线程中调用的,使用的还是Application的上下文
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          android.app.FragmentManager fm = activity.getFragmentManager();
          //通过fragmentGet()方法创建RequestManager对象
          return fragmentGet(
              activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
        }
    }

    @SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
    @Deprecated
    @NonNull
    private RequestManager fragmentGet(@NonNull Context context,
        @NonNull android.app.FragmentManager fm,
        @Nullable android.app.Fragment parentHint,
        boolean isParentVisible) {
        //创建一个没有UI的Fragment,Fragment可以监听Activity的生命周期,所以Glide通过该Fragment来间接的
        //监听对应的生命周期
        RequestManagerFragment current = getRequestManagerFragment(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的生命周期的,这里创建了一个没有UI的Fragment,通过它来间接的监听对应的生命周期,下面看一下是如果实现监听的:

public class RequestManagerFragment extends Fragment {
    //ActivityFragmentLifecycle类是生命周期回调的管理类
    private final ActivityFragmentLifecycle lifecycle;
    ......
    public RequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
    }
    ......
}

ActivityFragmentLifecycle它实现了LifeCycle接口,会将LifecycleListener的接口加入到ActivityFragmentLifecycle类中的Set集合中,当RequestManagerFragment的生命周期的方法触发时,会调用ActivityFragmentLifeCycle的相应方法。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {

    RequestManager(Glide glide,Lifecycle lifecycle, RequestManagerTreeNode treeNode,
          RequestTracker requestTracker,ConnectivityMonitorFactory factory,Context context) {
        this.glide = glide;
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        this.context = context;
        ......
        if (Util.isOnBackgroundThread()) {
          mainHandler.post(addSelfToLifecycle);
        } else {
          lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor);
        ......
        glide.registerRequestManager(this);
    }
}

RequestManager实现了LifeCycleListener接口,在RequestManager的构造方法中会将创建的RequestManager对象加入到ActivityFragmentLifeCycle的管理LifeCycleListener接口的集合中去,所以当ActivityFragmentLifeCycle的相应的方法调用时就会调用RequestManager对象的相应方法

2.load()方法

可以看到load()方法也有很多的重载,因为数据的来源不同。下面以参数为Uri的方法为例分析:

public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
}

asDrawable()方法就是创建一个RequestBuilder实例,然后调用该实例的load()方法,该方法最终会调用loadGeneric()方法,该方法的作用就是给RequestBuilder的成员变量private Object model;赋值。然后返回this,形成链式调用。下面看一下RequestBuilder的成员变量:

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
    // Used in generated subclasses
    protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
      new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA).priority(Priority.LOW)
          .skipMemoryCache(true);

    private final Context context;
    private final RequestManager requestManager;
    private final Class<TranscodeType> transcodeClass;
    private final Glide glide;
    private final GlideContext glideContext;

    @NonNull
    @SuppressWarnings("unchecked")
    private TransitionOptions<?, ? super TranscodeType> transitionOptions;

    @Nullable private Object model;
    // model may occasionally be null, so to enforce that load() was called, put a boolean rather
    // than relying on model not to be null.
    @Nullable private List<RequestListener<TranscodeType>> requestListeners;
    @Nullable private RequestBuilder<TranscodeType> thumbnailBuilder;
    @Nullable private RequestBuilder<TranscodeType> errorBuilder;
    @Nullable private Float thumbSizeMultiplier;
    private boolean isDefaultTransitionOptionsSet = true;
    private boolean isModelSet;
    private boolean isThumbnailBuilt;
}

//RequestBuilder的父类
public abstract class BaseRequestOptions<T extends BaseRequestOptions<T>> implements Cloneable {
    ......
    private int fields;
    private float sizeMultiplier = 1f;
    @NonNull
    private DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;
    @NonNull
    private Priority priority = Priority.NORMAL;
    @Nullable
    private Drawable errorPlaceholder;
    private int errorId;
    @Nullable
    private Drawable placeholderDrawable;
    private int placeholderId;
    private boolean isCacheable = true;
    private int overrideHeight = UNSET;
    private int overrideWidth = UNSET;
    @NonNull
    private Key signature = EmptySignature.obtain();
    private boolean isTransformationRequired;
    private boolean isTransformationAllowed = true;
    @Nullable
    private Drawable fallbackDrawable;
    private int fallbackId;
    @NonNull
    private Options options = new Options();
    @NonNull
    private Map<Class<?>, Transformation<?>> transformations = new CachedHashCodeArrayMap<>();
    @NonNull
    private Class<?> resourceClass = Object.class;
    private boolean isLocked;
    @Nullable
    private Resources.Theme theme;
    private boolean isAutoCloneEnabled;
    private boolean useUnlimitedSourceGeneratorsPool;
    private boolean onlyRetrieveFromCache;
    private boolean isScaleOnlyOrNoTransform = true;
    private boolean useAnimationPool;
    ......
}

RequestBuilder及其父类的成员变量可以看到,关于Glide的配置的属性都在这里面,比如:overrideHeight 、overrideWidth 、placeholderDrawable、priority等。在该类的构造方法中会对这些属性有默认的初始化赋值。

3.into()方法

在上面配置好imageUrl和一些参数设置之后调用into()方法,就可以实现显示图片的功能了。下面看一个该方法的代码:

@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    //判断是否在主线程,否则跑出异常
    Util.assertMainThread();
    Preconditions.checkNotNull(view);
    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      根据ImageView的scaleType属性来给对应的配置属性赋值
      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.
      }
    }
    //调用into()方法,传入了一个Target参数
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
}

从上述代码中可以看出,into()方法必须要主线程中调用,否则抛出异常。在该方法中将传入的ImageView对象封装成了Target对象通过glideContext.buildImageViewTarget(view, transcodeClass)方法,下面就看一下该方法的具体实现:

public class ImageViewTargetFactory {
  @NonNull
  @SuppressWarnings("unchecked")
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      //如果调用了asBitmap()方法
      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)");
    }
  }
}

BitmapImageViewTarget为例,就是对ImageView封装了一层,调用对应的方法其实就是调用ImageView的相应方法。比如如下所示:

public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
    ......
    @Override
    protected void setResource(Bitmap resource) {
        view.setImageBitmap(resource);
    }
    ......
}

创建Target实例以后就会调用参数为该实例的into()方法,下面看一下该方法的实现:

private <Y extends Target<TranscodeType>> Y into(@NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,Executor callbackExecutor) {
    ......
    //构建请求
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //获取上一个请求
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      //如果是相同的请求直接复用
      request.recycle();
      ......
      if (!Preconditions.checkNotNull(previous).isRunning()) {
      ......
        previous.begin();
      }
      return target;
    }
    requestManager.clear(target);
    //target与request绑定,通过View.setTag(obj)
    target.setRequest(request);
    requestManager.track(target, request);
    return target;
}

下面继续看一下requestManager.track(target, request);方法:

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

最终调用requestTracker.runRequest(request);方法来执行请求,继续看一下该请求的实现:

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(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);
    }
}

又会调用request.begin();来开始请求:

@Override
public synchronized void begin() {
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    ......
    if (status == Status.RUNNING) {
      throw new IllegalArgumentException("Cannot restart a running request");
    }
    if (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }
    status = Status.WAITING_FOR_SIZE;
    //设置图片的大小
    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());
    }
    ......
}

如果设置了图片的大小override(300,300),图片的宽高就使用没有,没有设置的话,就使用ImageView的宽高target.getSize(),最终都会调用onSizeReady()方法来设置图片大小以及开始真正的请求。

public synchronized void onSizeReady(int width, int height) {
    ......
    status = Status.RUNNING;
    float sizeMultiplier = requestOptions.getSizeMultiplier();
    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
    ......
    loadStatus =
        //开始真正的请求
        engine.load(参数省略...);
    ......
}

通过engineload()方法来执行请求:

public synchronized <R> LoadStatus load(参数省略...){
    ......
    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);
    ......
}

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

KotlinAndroid

EShop

推荐阅读更多精彩内容