先写一个简单的例子:
Glide.with(context).load(url).into(imageView);
看源码我们要记住一个原则,就是站在宏观的角度先去理解他。再慢慢延伸到细节。glide的源码比较多。我们先沿着主线去一步步分析它。glide使用了外观模式,一般第三方的sdk通常都会这么做,节省用户学习使用的成本。我们来看看glide.with。
1.Glide#with
这里就是返回一个requestManager。有6中重载的方法,我们这里就以通常的activity来处理。
2.Glide#getRetriever
这里就是做了一个非空判断,然后我们先看Glide.get。
3.Glide#get
这里就是生成一个单例的glide对象。当然里面通过GlideBuilder构建glide的配置。比如缓存策略等。我们回到2,接着看一下getRequestManagerRetriever。
4.Glide#getRequestManagerRetriever
这里就是拿到glide初始化的时候生成的requestManagerRetriever。我们来看一下glide生成时候requestManagerRetriever的生成过程。
5.GlideBuilder#build
Glide build(@NonNull Context context) {
...
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
这里我们知道requestManagerFactory在本例中为空。然后看一下RequestManagerRetriever构造。
6.RequestManagerRetriever#RequestManagerRetriever
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
初始化了一个主线程的handler,这里factory为null 继续看DEFAULT_FACTORY。
7.RequestManagerRetriever#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);
}
};
这里生成RequestManagerRetriever的时候实现了RequestManagerFactory接口来提供requestManager实例。好了,这时候我们可以回到第一步看一下get方法。
8.RequestManagerRetriever#get
这里先是判断activity在不在前台,我们这里按前台处理,还是一个原则,宏观处理沿着一条主线走下去。
接着判断activity没有销毁,得到FragmentManager,最后看一下fragmentGet方法。
9.RequestManagerRetriever#fragmentGet
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
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;
}
接着我们来看一下getRequestManagerFragment方法。
10.RequestManagerRetriever#getRequestManagerFragment
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
这里先从fragmentManager中获取是否有RequestManagerFragment,这里第一次是没有的,然后判断pendingRequestManagerFragments有没有。为什么还需要pendingRequestManagerFragments辅助判断呢,因为fragmentManager是以消息机制的方法提交的,这里不可避免的会延迟。使用pendingRequestManagerFragments避免创建两次。这里glide使用了一个很巧妙的方式来绑定activity的生命周期,就是通过创建一个activity的fragment来间接监听activity的生命周期。通过RequestManagerFragment中ActivityFragmentLifecycle类来通知各个实现LifecycleListener接口的类。这里得到RequestManagerFragment,我们回到第9步。第一次是没有RequestManager的。我们通过glide初始化的factory。最终得到生成的requestManager对象。接着,我们load方法。
10.RequestManager#load
这里返回的是RequestBuilder。显然是request的各种配置类。我们接着来看一下asDrawable方法。
11.RequestManager#asDrawable
@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);
}
这里扩展一个小知识,就是使用一个未定义的泛型时,应该如上这样写。这里拿到生成的RequestBuilder。这里面会涉及图片加载参数的设置。我们再回到第10步。看一下load方法
12.RequestBuilder#load
这里会把url赋值给model,并且把ismodelset置为true(说明model已经被赋值)。这样load方法就分析完了。我们来看一下into。
13.RequestBuilder#into
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(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
这里先判断了是否在主线程,非空判断。获取设置的RequestOptions,因为这里我们没有设置所以为第5步GlideBuilder生成过程中默认的RequestOptions。所以我们可以略过这段配置直接看下面的into,先来看into的第一个参数buildImageViewTarget。
14.GlideContext#buildImageViewTarget
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)");
}
}
}
因为transcodeClass就是我们第11步传的drawable。很明显我们会返回一个DrawableimageViewTarget类。我们接着返回13步看一下into方法。
15.RequestBuilder#into
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;
}
先是同样的判断主线程,非空。isModelSet是否设置,得到RequestOptions,接着我们看一下buildRequest方法。
16.RequestBuilder#buildRequest
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;
}
int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.requestOptions.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
这里因为没有设置errorBuilder,我直接往下看。看一下buildThumbnailRequestRecursive方法。
17.RequestBuilder#buildThumbnailRequestRecursive
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
if (thumbnailBuilder != null) {
...
} else if (thumbSizeMultiplier != null) {
...
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
}
}
好吧又是一个很长的方法...继续看。因为我们没有设置thumbnailBuilder和thumbSizeMultiplier。我们直接看最后面obtainRequest方法。
18.RequestBuilder#obtainRequest
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight) {
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory());
}
然后是obtain方法。
19.SingleRequest#obtain
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object model,
Class<R> transcodeClass,
RequestOptions requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> requestListeners,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory) {
@SuppressWarnings("unchecked") SingleRequest<R> request =
(SingleRequest<R>) POOL.acquire();
if (request == null) {
request = new SingleRequest<>();
}
request.init(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
engine,
animationFactory);
return request;
}
这里用了一种享元的一种设计模式。可以节省内存开销。有就得到request。当然第一次是没有的。最后init方法只是一下参数设置,我们就不看了。我们回到第15步继续看into方法。
这里判断了是否可以复用。很明显没有上次请求过。接着看一下clear方法。
20.RequestManager#clear
当是主线程的是或者非主线程时处理逻辑是一样的。这里就是看是否这个target有绑定的request,有的话解绑一下。把这个target绑定到这个新的request上去。回到第15步,track方法。
21.RequestManager#track
void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
其实就是处理target和request在生命周期变化时而变化。比如暂停,重新开始等等。最后分析一下runRequest方法。
22.RequestTracker#runRequest
如果是暂停的状态,request就会走clear方法,并且把这个request加入到准备加载的pendingrequests集合中(因为requests是weakhashmap 容易被回收,这里放入到pendingrequests里也是防止被回收)。如果是活跃的状态,则会执行begin方法。接下来,我们看看request.begin方法。
23.SingleRequest#begin
这里的model就是我们设置的url,当是null的时候直接调用onLoadFailed方法返回失败。不可能开启一个已经标记为RUNNING的request。如果标记为COMPLETE。直接返回onresourceReady。做下载后的处理。这里我们是第一次使用,所以我们会走下面的过程,这里赋值WAITIND_FOR_SIZE.当没有overrideWidth和overrideHeight无效时,我们来等待view的绘制。这里我们假设绘制好了,我们来看一下onSizeReady。
24.SingleRequest#onSizeReady
这里就是先判断一下是否在等待view的绘制。如果没有直接结束。绘制完成的话赋值RUNNING。然后loadStatus = engine.load。初始化一些缓存策略,图片显示策略等待。这里engine比较复杂,我们先看他的结果是怎么处理的。当engine调用load的时候会把当前的SingleRequest的回调绑定到Engine中。这样我们来看一下ResourceCallback。
所以,当engine处理完就把结果交给SingleRequest来处理,最终交给target。我们最后回到23步。符合条件的时候加载target的占位图。
到这里就结束了整个流畅,下一章我们来分析一些engine的过程。