源码方面主要从最基本的三个方法入手:with,load,into。
Glide.with
Glide.with()方法根据不同上下文对象有多个重载方法,源码如下:
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getContext()).get(fragment);
}
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
可以看到,每个重载方法内部都首先调用getRetriever()方法获取一个RequestManagerRetriever对象,然后调用其get方法来返回RequestManager。
传入getRetriever()的参数都是Context,而RequestManagerRetriever.get()方法传入的参数各不相同,所以生命周期的绑定肯定发生在get方法中。
下面,接着分析getRetriever()方法。
getRetriever(Context)
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
因入参context为fragment.getActivity()时,context可能为空,所以这里进行了一次判断。然后就调用了Glide.get(context)创建了一个Glide,最后将requestManagerRetriever返回即可。
获取Glide实例
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
if (isInitializing) {
throw new IllegalStateException(
"You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context, generatedAppGlideModule);
isInitializing = false;
}
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Context applicationContext = context.getApplicationContext();
...
// 调用GlideBuilder.build方法创建Glide
Glide glide = builder.build(applicationContext);
...
// 注册内存管理的回调,因为Glide实现了ComponentCallbacks2接口
applicationContext.registerComponentCallbacks(glide);
// 保存glide实例到静态变量中
Glide.glide = glide;
}
查看GlideBuilder.build方法:
Glide build(@NonNull Context context) {
//获取图片的线程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
//磁盘缓存的线程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
//动画的线程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//创建内存大小控制器
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
//创建网络监听的工厂
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
// 使用缓存,则创建bitmap对象池
bitmapPool = new LruBitmapPool(size);
} else {
// 不使用缓存
bitmapPool = new BitmapPoolAdapter();
}
}
//创建对象数组缓存池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
//创建内存缓存
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(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
GlideExperiments experiments = glideExperimentsBuilder.build();
//创建请求管理类,其构造方法中会实例化一个主线程的handler对象,用于线程的切换
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory, experiments);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
experiments);
}
这里的requestManagerRetriever直接调用了构造器,且传入参数实际上为null,在RequestManagerRetriever的构造器方法中会为此创建一个默认的DEFAULT_FACTORY。
public RequestManagerRetriever(
@Nullable RequestManagerFactory factory, GlideExperiments experiments) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
frameWaiter = buildFrameWaiter(experiments);
}
目前为止,Glide单例已经被创建出来了,其requestManagerRetriever会作为getRetriever(Context)的返回值返回。
RequestManagerRetriever.get系列方法
RequestManagerRetriever类的get方法,会有相关重载方法。
public class RequestManagerRetriever implements Handler.Callback {
....
/** The top application level RequestManager. */
private volatile RequestManager applicationManager;
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) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
// TODO(b/27524013): Factor out this Glide.get() call.
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
// Only unwrap a ContextWrapper if the baseContext has a non-null application context.
// Context#createPackageContext may return a Context without an Application instance,
// in which case a ContextWrapper may be used to attach one.
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
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);
frameWaiter.registerSelf(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(
fragment.getContext(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getContext().getApplicationContext());
} else {
// In some unusual cases, it's possible to have a Fragment not hosted by an activity. There's
// not all that much we can do here. Most apps will be started with a standard activity. If
// we manage not to register the first frame waiter for a while, the consequences are not
// catastrophic, we'll just use some extra memory.
if (fragment.getActivity() != null) {
frameWaiter.registerSelf(fragment.getActivity());
}
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible());
}
}
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else if (activity instanceof FragmentActivity) {
return get((FragmentActivity) activity);
} else {
assertNotDestroyed(activity);
frameWaiter.registerSelf(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@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());
}
// Support Fragments.
// Although the user might have non-support Fragments attached to FragmentActivity, searching
// for non-support Fragments is so expensive pre O and that should be rare enough that we
// prefer to just fall back to the Activity directly.
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
return fragment != null ? get(fragment) : get((FragmentActivity) activity);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
}
从上面一系列get()重载方法,方法内部会首先判断当前线程是不是后台线程,如果是后台线程最终会调用getApplicationManager()方法返回RequestManager;
如果当前线程不是后台线程,get(Context)方法根据情况会调用get(FragmentActivity)、get(Activity)、getApplicationManager(context)方法;get(View)方法根据情况会调用get(Fragment)、get(Activity)方法;get(Fragment)和get(FragmentActivity)方法都会调用supportFragmentGet方法。
Glide会使用一个加载目标所在的宿主Activity或Fragment的子Fragment来安全保存一个RequestManager,而RequestManager被Glide用来开始、停止、管理Glide请求。而supportFragmentGet就是创建/获取这个SupportRequestManagerFragment,并返回其持有的RequestManager的方法。
private final RequestManagerFactory factory;
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
// 获取一个SupportRequestManagerFragment
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
// 获取里面的RequestManager对象
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);
// This is a bit of hack, we're going to start the RequestManager, but not the
// corresponding Lifecycle. It's safe to start the RequestManager, but starting the
// Lifecycle might trigger memory leaks. See b/154405040
if (isParentVisible) {
requestManager.onStart();
}
// 设置到SupportRequestManagerFragment里面,下次就不需要创建了
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
// 已经添加过了,可以直接返回
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 从map中获取,取到也可以返回了
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
// 都没有,那么就创建一个
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
// 将刚创建的fragment缓存起来
pendingSupportRequestManagerFragments.put(fm, current);
/ 将fragment添加到页面中
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
// 以fm为key从pendingSupportRequestManagerFragments中删除
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
从上面的方法可以看出,成功创建了一个RequestManager对象。requestManager对象是由factory.build()方法创建出来。下面就看下factory如何创建的:
private final RequestManagerFactory factory;
public RequestManagerRetriever(
@Nullable RequestManagerFactory factory, GlideExperiments experiments) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
frameWaiter = buildFrameWaiter(experiments);
}
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);
}
};
从上文分析getRetriever(Context)可以知道,factory其实就是DEFAULT_FACTORY。到目前为止,Glide.with已经分析完毕。
流程图:
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);
}
从上面的方法中,可以看出load重载方法都会先调用asDrawable()。接下来,看下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);
}
从上面可以看出,asDrawable()方法调用as()方法,并传入Drawable.class;而as方法创建一个图片类型为Drawable类型的RequestBuilder请求。下面接着看下RequestBuilder:
RequestBuilder.load
RequestManager.load方法都会调用对应的RequestBuilder.load重载方法。
protected RequestBuilder(Glide glide, RequestManager requestManager,
Class<TranscodeType> transcodeClass, Context context) {
this.glide = glide;
this.requestManager = requestManager;
//注意,这里传入的是Drawable.class
this.transcodeClass = transcodeClass;
this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.requestOptions = defaultRequestOptions;
this.glideContext = glide.getGlideContext();
}
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
return loadGeneric(uri);
}
public RequestBuilder<TranscodeType> load(@Nullable File file) {
return loadGeneric(file);
}
public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
return loadGeneric(drawable).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return loadGeneric(resourceId).apply(signatureOf(AndroidResourceSignature.obtain(context)));
}
从上面的代码可以看出,RequestBuilder.load的各个方法基本上都会直接转发给loadGeneric方法,只有少数的方法才会apply额外的options。接着,看下loadGeneric方法:
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
if (isAutoCloneEnabled()) {
return clone().loadGeneric(model);
}
this.model = model;
isModelSet = true;
return selfOrThrowIfLocked();
}
protected final T selfOrThrowIfLocked() {
if (isLocked) {
throw new IllegalStateException("You cannot modify locked T, consider clone()");
}
return self();
}
private T self() {
return (T) this;
}
该方法主要是将图片源保存起来,并设置是否设置了图片源的标识isModelSet=true,最后返回了RequestBuilder自身this
流程图:
RequestBuilder.into
通过RequestBuilder.into方法设置目标view
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
//熟悉的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.
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
从以上源码来看,into(ImageView)方法的实现,里面会先判断需不需要对图片进行裁切,然后调用别的into重载方法。接下来,重点看最后返回调用into()重载方法,它将view通过buildImageViewTarget方法转为target,transcodeClass为Bitmap.class或Drawable.class。
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);
}
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)");
}
}
}
这里创建的是DrawableImageViewTarget,然后DrawableImageViewTarget被作为参数传入into方法。
上文中,into() 方法中入参参数Executors.mainThreadExecutor()
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);
}
};
Executors.mainThreadExecutor()就是一个使用MainLooper的Handler,在execute Runnable时使用此Handler post出去。
现在,into重载方法入参参数已经讲完了,可以看下该方法:
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//重点1:创建了一个SingleRequest类型 request 对象
Request request = buildRequest(target, targetListener, options, callbackExecutor);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
//将target原先所关联的请求断开
requestManager.clear(target);
//并设置为新的请求,
target.setRequest(request);
// 然后通过requestManager.track()进行一些列的加载和处理显示操作
// 重点2:真正开始网络图片的加载
requestManager.track(target, request);
return target;
}
重点1:buildRequest
跟踪一下buildRequest的流程,看看是如何创建出SingleRequest的
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener, // null
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(), // Priority.NORMAL
requestOptions.getOverrideWidth(), // UNSET
requestOptions.getOverrideHeight(), // UNSET
requestOptions,
callbackExecutor); // Executors.mainThreadExecutor()
}
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
....
// 如何获得SingleRequest
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener, // null
parentCoordinator, // null
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
...
}
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
// thumbnail重载方法没有调用过,所以会走最后的else case
if (thumbnailBuilder != null) {
...
} else if (thumbSizeMultiplier != null) {
...
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
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);
}
上面代码中,中间好多是处理缩略图的逻辑,最后会到obtainRequest()方法中。 SingleRequest 类通过静态obtain() 方法返回Request。
重点2:RequestManager.track
// RequestManager
@GuardedBy("this")
private final TargetTracker targetTracker = new TargetTracker();
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
// 将target保存到了内部的targets中
targetTracker.track(target);
requestTracker.runRequest(request);
}
targetTracker在声明的时候直接初始化,该类的作用是保存所有的Target并向它们转发生命周期事件;requestTracker在RequestManager的构造器中传入了new RequestTracker(),该类的作用管理所有状态的请求。
//RequestTracker.java
public void runRequest(@NonNull Request request) {
// requests 正在请求集合
requests.add(request);
if (!isPaused) {
request.begin();
} else {
request.clear();
// pendingRequests 等待请求集合
pendingRequests.add(request);
}
}
isPaused默认为false,会执行request.begin()方法。上面说到过,这里的request实际上是SingleRequest对象,我们看一下它的begin()方法。
// SingleRequest
public void begin() {
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
// 如果model为空,会调用监听器的onLoadFailed处理
// 若无法处理,则展示失败时的占位图
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
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");
}
// 如果我们在请求完成后想重新开始加载,那么就会返回已经加载好的资源
// 如果由于view尺寸的改变,我们的确需要重新来加载,此时我们需要明确地清除View或Target
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
// 如果指定了overrideWidth和overrideHeight,那么直接调用onSizeReady方法,否则会获取ImageView的宽、高
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//将目标view的宽高传入onSizeReady
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));
}
}
}
接下来会获取要加载图片的size并调用onSizeReady方法,我们直接看该方法:
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
synchronized (requestLock) {
...
if (status != Status.WAITING_FOR_SIZE) {
return;
}
//修改status为running
status = Status.RUNNING;
// 将原始尺寸与0~1之间的系数相乘,取最接近的整数值,得到新的尺寸
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
//调用Engine.load对请求进行处理
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);
// status目前显然是RUNNING状态,所以不会将loadStatus设置为null
if (status != Status.RUNNING) {
loadStatus = null;
}
}
}
Engine.load
engine.load 是开始请求的关键代码了,Engine是负责开始加载,管理active、cached状态资源的类。
// Engine
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
EngineResource<?> memoryResource;
synchronized (this) {
// 获取缓存中的图片资源
// 分析1
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// 缓存中没有则等待或新开一个job获取图片资源
// 分析2
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}
// Avoid calling back while holding the engine lock, doing so makes it easier for callers to
// deadlock.
cb.onResourceReady(
memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return null;
}
上面的方法,主要是先通过loadFromMemory获取缓存中的图片资源,取不到则调用waitForExistingOrStartNewJob。
分析1:Engine.loadFromMemory
@Nullable
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
//判断是否允许内存缓存
if (!isMemoryCacheable) {
return null;
}
//从活动缓存中取
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return active;
}
//从内存缓存中取
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return cached;
}
return null;
}
该方法中,首先从ActiveResources中取资源,如果获取不到,就从内存缓存中取资源。活动缓存和内存缓存属于运行时缓存。
接下来,查看loadFromActiveResources()方法:
// Engine
private final ActiveResources activeResources;
@Nullable
private EngineResource<?> loadFromActiveResources(Key key) {
EngineResource<?> active = activeResources.get(key);
if (active != null) {
active.acquire();
}
return active;
}
// ActiveResources
final class ActiveResources {
final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
....
@Nullable
synchronized EngineResource<?> get(Key key) {
ResourceWeakReference activeRef = activeEngineResources.get(key);
if (activeRef == null) {
return null;
}
EngineResource<?> active = activeRef.get();
if (active == null) {
cleanupActiveReference(activeRef);
}
return active;
}
....
}
// EngineResource<Z>
class EngineResource<Z> implements Resource<Z> {
...
private int acquired;
private boolean isRecycled;
...
synchronized void acquire() {
if (isRecycled) {
throw new IllegalStateException("Cannot acquire a recycled resource");
}
++acquired;
}
}
从上面源码来看,ActiveResources维护了一个value为弱引用HashMap<Key,ResourceWeakReference>, 调用其get方法获取图片资源,如果取到则调用acquire对 对象的引用数量 进行加一操作,内存缓存是通过计数散列算法来进行相应的操作的,如果对象的计数树为0,则说明暂无其他对象引用此资源,那么此资源可以被释放了。
分析2:Engine.waitForExistingOrStartNewJob
loadFromMemory()方法取不到,则调用waitForExistingOrStartNewJob()去获取图片资源。
final class Jobs {
private final Map<Key, EngineJob<?>> jobs = new HashMap<>();
private final Map<Key, EngineJob<?>> onlyCacheJobs = new HashMap<>();
...
}
private <R> LoadStatus waitForExistingOrStartNewJob(...) {
//先从jobs中取EngineJob
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
// 检测有没有真正执行的缓存可用(磁盘缓存)
if (current != null) {
current.addCallback(cb, callbackExecutor);
//取到则直接创建一个LoadStatus返回
return new LoadStatus(cb, current);
}
//取不到则通过engineJobFactory.build创建一个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加入到jobs
jobs.put(key, engineJob);
//注册ResourceCallback
engineJob.addCallback(cb, callbackExecutor);
//调用start开启线程获取图片
// 执行decodeJob任务
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
在上面的方法中,最重要是engineJob.start() 开启线程获取图片,源码如下:
// EngineJob
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
// willDecodeFromCache() 为true
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
// executor 为diskCacheExecutor
executor.execute(decodeJob);
}
boolean willDecodeFromCache() {
// firstStage返回值为Stage.RESOURCE_CACHE
Stage firstStage = getNextStage(Stage.INITIALIZE);
return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
}
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// Skip loading from source if the user opted to only retrieve the resource from cache.
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
从上面的start()方法中,GlideExecutor类型的executor值为diskCacheExecutor,它的初始化操作是放在GlideBuilder.build()方法里。
// GlideBuilder
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
public final class GlideExecutor implements ExecutorService {
public static GlideExecutor newDiskCacheExecutor() {
return newDiskCacheBuilder().build();
}
public static GlideExecutor.Builder newDiskCacheBuilder() {
return new GlideExecutor.Builder(/*preventNetworkOperations=*/ true)
.setThreadCount(DEFAULT_DISK_CACHE_EXECUTOR_THREADS)
.setName(DEFAULT_DISK_CACHE_EXECUTOR_NAME);
}
GlideExecutor(ExecutorService delegate) {
this.delegate = delegate;
}
public void execute(@NonNull Runnable command) {
delegate.execute(command);
}
public static final class Builder {
...
public GlideExecutor build() {
if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException(
"Name must be non-null and non-empty, but given: " + name);
}
ThreadPoolExecutor executor =
new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
/*keepAliveTime=*/ threadTimeoutMillis,
TimeUnit.MILLISECONDS,
new PriorityBlockingQueue<Runnable>(),
new DefaultThreadFactory(name, uncaughtThrowableStrategy, preventNetworkOperations));
if (threadTimeoutMillis != NO_THREAD_TIMEOUT) {
executor.allowCoreThreadTimeOut(true);
}
return new GlideExecutor(executor);
}
}
}
从上面源码来看,GlideExecutor其实就是个线程池。并且,DecodeJob是实现Runnable接口的类,放到线程池中去执行。不管是磁盘缓存还是内存缓存最终都会调用DecodeJob,接下来看DecodeJob 类重点run() 方法。
DecodeJob.run
DecodeJob 的run()方法里面重点关注runWrapped()操作。
private enum Stage {
/** The initial stage. */
INITIALIZE,
/** Decode from a cached resource. */
RESOURCE_CACHE,
/** Decode from cached source data. */
DATA_CACHE,
/** Decode from retrieved source. */
SOURCE,
/** Encoding transformed resources after a successful load. */
ENCODE,
/** No more viable stages. */
FINISHED,
}
class DecodeJob<R>
implements DataFetcherGenerator.FetcherReadyCallback,
Runnable, Comparable<DecodeJob<?>>, Poolable {
private volatile DataFetcherGenerator currentGenerator;
public void run() {
...
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (
...
}
private void runWrapped() {
//runReason在DecodeJob初始化的时候初始值是INITIALIZE
switch (runReason) {
case INITIALIZE:// 首次提交任务
//调用getNextStage后返回Stage.RESOURCE_CACHE
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:// 尝试从磁盘缓存切到内存缓存
runGenerators();
break;
case DECODE_DATA:// 解码原数据,也就是去加载资源
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
// ResourceCacheGenerator:获取采样后、transformed后资源文件的缓存文件
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
// DataCacheGenerator:获取原始的没有修改过的资源文件的缓存文件
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
// SourceGenerator:获取原始源数据
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
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();
}
}
}
getNextGenerator()方法的RESOURCE_CACHE和DATA_CACHE这2种策略必须使用Glide加载图片设置缓存策略,才会调用这2种;否则直接会调用SOURCE情况,请求图片资源。
上面的runGenerators()方法会依次调用各个状态生成的ResourceCacheGenerator、DataCacheGenerator、SourceGenerator的startNext()尝试fetch数据,直到有某个状态的DataFetcherGenerator.startNext()方法可以胜任。若状态抵达到了Stage.FINISHED或job被取消,且所有状态的DataFetcherGenerator.startNext()都无法满足条件,则调用SingleRequest.onLoadFailed进行错误处理。
ResourceCacheGenerator
接着,继续看ResourceCacheGenerator.startNext()方法。
// ResourceCacheGenerator
private final DecodeHelper<?> helper;
@Override
public boolean startNext() {
// list里面只有一个GlideUrl对象
List<Key> sourceIds = helper.getCacheKeys();
if (sourceIds.isEmpty()) {
return false;
}
// list集合返回类型为: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());
}
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);
currentKey =
new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
helper.getArrayPool(),
sourceId,
helper.getSignature(),
helper.getWidth(),
helper.getHeight(),
transformation,
resourceClass,
helper.getOptions());
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
SourceGenerator
由于第一次加载,本地缓存文件肯定是没有的。看下SourceGenerator,看它是如何获取数据的。
private int loadDataListIndex;
@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 list
loadData = helper.getLoadData().get(loadDataListIndex++);
// 找出符合条件的LoadData
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
startNextLoad(loadData);
}
}
return started;
}
private boolean hasNextModelLoader() {
return loadDataListIndex < helper.getLoadData().size();
}
private void startNextLoad(final LoadData<?> toStart) {
// fetcher是HttpUrlFetcher
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback<Object>() {
@Override
public void onDataReady(@Nullable Object data) {
if (isCurrentRequest(toStart)) {
onDataReadyInternal(toStart, data);
}
}
@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
startNextLoad()方法根据HttpUrlFetcher去加载数据。为啥是HttpUrlFetcher?看如下代码:
// DecodeHelper
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
//
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
// HttpGlideUrlLoader
public LoadData<InputStream> buildLoadData(
@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
// spent parsing urls.
GlideUrl url = model;
if (modelCache != null) {
url = modelCache.get(model, 0, 0);
if (url == null) {
modelCache.put(model, 0, 0, model);
url = model;
}
}
int timeout = options.get(TIMEOUT);
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
接着,继续分析HttpUrlFetcher的loadData()方法。
//HttpUrlFetcher.java
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
try {
//请求网络
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//将数据返回回去
callback.onDataReady(result);
} catch (IOException e) {
callback.onLoadFailed(e);
} finally {
}
}
private InputStream loadDataWithRedirects(
URL url, int redirects, URL lastUrl, Map<String, String> headers) throws HttpException {
...
urlConnection = buildAndConfigureConnection(url, headers);
try {
// 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();
} catch (IOException e) {
throw new HttpException(
"Failed to connect or obtain data", getHttpStatusCodeOrInvalid(urlConnection), e);
}
if (isCancelled) {
return null;
}
final int statusCode = getHttpStatusCodeOrInvalid(urlConnection);
...
}
// 网络请求相关的代码
private HttpURLConnection buildAndConfigureConnection(URL url, Map<String, String> headers)
throws HttpException {
HttpURLConnection urlConnection;
try {
urlConnection = connectionFactory.build(url);
} catch (IOException e) {
throw new HttpException("URL.openConnection threw", /*statusCode=*/ 0, e);
}
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Stop the urlConnection instance of HttpUrlConnection from following redirects so that
// redirects will be handled by recursive calls to this method, loadDataWithRedirects.
urlConnection.setInstanceFollowRedirects(false);
return urlConnection;
}
通过HttpURLConnection进行的网络请求,并且结果就是通过urlConnection.getInputStream();这里拿到了结果后,就返回了,然后就是上面的callback.onDataReady(result);进行回调处理结果。
SourceGenerator.onDataReadyInternal
从上面SourceGenerator.startNextNext中的loadData.fetcher.loadData的入参DataCallback的onDataReady我们知道,如果请求成功,会将资源通过onDataReady传递回去,其中调用了onDataReadyInternal,代码如下:
void onDataReadyInternal(LoadData<?> loadData, 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为DecodeJob
cb.onDataFetcherReady(
loadData.sourceKey,
data,
loadData.fetcher,
loadData.fetcher.getDataSource(),
originalKey);
}
}
看一下DecodeJob.onDataFetcherReady
// DecodeJob
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;
this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
// 解码图片资源
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey(
"Retrieved data",
startFetchTime,
"data: "
+ currentData
+ ", cache key: "
+ currentSourceKey
+ ", fetcher: "
+ currentFetcher);
}
Resource<R> resource = null;
try {
// 分析1
// 从数据中解码得到资源
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
// 分析2
notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);
} else {
runGenerators();
}
}
decodeFromRetrievedData()方法会先调用decodeFromData方法进行解码,然后调用notifyEncodeAndRelease方法进行缓存。
分析1:decodeFromData调用流程
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();
}
}
@SuppressWarnings("unchecked")
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
//将解码交给LoadPath对象
return runLoadPath(data, dataSource, path);
}
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();
}
}
从decodeFromData()方法可以看出,该方法内部又调用decodeFromFetcher()方法;在decodeFromFetcher()方法中会获取LoadPath,然后调用runLoadPath()方法解析成资源。
在runLoadPath()方法中会调用path.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);
}
}
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;
}
在loadWithExceptionList()方法中,对于每条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 {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
@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);
}
}
@NonNull
private Resource<ResourceType> decodeResourceWithList(
DataRewinder<DataType> rewinder,
int width,
int height,
@NonNull Options options,
List<Throwable> exceptions)
throws GlideException {
Resource<ResourceType> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
//根据DataType, ResourceType区别,分发给不同的解码器
result = decoder.decode(data, width, height, options);
}
// Some decoders throw unexpectedly. If they do, we shouldn't fail the entire load path, but
// instead log and continue. See #2406 for an example.
} catch (IOException | RuntimeException | OutOfMemoryError e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Failed to decode data for " + decoder, e);
}
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
上面的decoder其实是StreamBitmapDecoder,在初始化Glide的时候就初始化好了。
// StreamBitmapDecoder
public Resource<Bitmap> decode(@NonNull InputStream source, int width, int height,
@NonNull Options options)
throws IOException {
...
//这里又将解码任务交给了Downsampler
return downsampler.decode(invalidatingStream, width, height, options, callbacks);
}
上面的方法会将decode出来的Bitmap包装成为一个BitmapResource对象。然后就一直往上返回,返回到DecodePath.decode方法中。 继续执行如下代码:
// DecodePath
Resource<ResourceType> transformed=callback.onResourceDecoded(decoded);
// DecodeJob
@Synthetic
@NonNull
<Z> Resource<Z> onResourceDecoded(DataSource dataSource, @NonNull Resource<Z> decoded) {
@SuppressWarnings("unchecked")
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
// TODO: Make this the responsibility of the Transformation.
if (!decoded.equals(transformed)) {
decoded.recycle();
}
final EncodeStrategy encodeStrategy;
final ResourceEncoder<Z> encoder;
if (decodeHelper.isResourceEncoderAvailable(transformed)) {
encoder = decodeHelper.getResultEncoder(transformed);
encodeStrategy = encoder.getEncodeStrategy(options);
} else {
encoder = null;
encodeStrategy = EncodeStrategy.NONE;
}
Resource<Z> result = transformed;
boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
if (diskCacheStrategy.isResourceCacheable(
isFromAlternateCacheKey, dataSource, encodeStrategy)) {
if (encoder == null) {
throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
}
final Key key;
switch (encodeStrategy) {
case SOURCE:
key = new DataCacheKey(currentSourceKey, signature);
break;
case TRANSFORMED:
key =
new ResourceCacheKey(
decodeHelper.getArrayPool(),
currentSourceKey,
signature,
width,
height,
appliedTransformation,
resourceSubClass,
options);
break;
default:
throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
}
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
}
return result;
}
这里会调用DecodeJob.onResourceDecoded(DataSource,Resource)方法。至此,resource已经decode完毕。
分析2:notifyEncodeAndRelease调用流程
返回到DecodeJob.decodeFromRetrievedData()方法中,会调用notifyEncodeAndRelease方法。下面看看其代码:
private void notifyEncodeAndRelease(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
// resource是BitmapResource类型,实现了Initializable接口
if (resource instanceof Initializable) {
// initialize方法调用了bitmap.prepareToDraw()
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
// 通知回调,资源已经就绪
notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// Call onEncodeComplete outside the finally block so that it's not called if the encode process
// 进行清理工作
onEncodeComplete();
}
private void notifyComplete(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
}
上面这段代码重点在于notifyComplete方法,该方法内部会调用callback.onResourceReady(resource, dataSource)将结果传递给回调,这里的回调是EngineJob。
// EngineJob
final ResourceCallbacksAndExecutors cbs = new ResourceCallbacksAndExecutors();
@Override
public void onResourceReady(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
this.isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey;
}
notifyCallbacksOfResult();
}
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
// TODO: Seems like we might as well put this in the memory cache instead of just recycling
// it since we've gotten this far...
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");
}
// engineResourceFactory默认为EngineResourceFactory,其build方法就是new一个对应的资源
engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
...
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
// listener就是Engine,该方法将资源保存到activeResources中
engineJobListener.onEngineJobComplete(this, localKey, localResource);
// entry.executor就是Glide.with.load.into中出现的Executors.mainThreadExecutor()
// entry.cb就是SingleRequest
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
// Engine
public synchronized void onEngineJobComplete(
EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null && resource.isMemoryCacheable()) {
activeResources.activate(key, resource);
}
jobs.removeIfCurrent(key, engineJob);
}
继续看 engineJobListener.onEngineJobComplete()这行代码,设置资源的回调,将资源放入activeResources中,资源变为active状态,最后将engineJob从Jobs中移除。
接下来,注重看下 CallResourceReady类
// EngineJob
private class CallResourceReady implements Runnable {
private final ResourceCallback cb;
CallResourceReady(ResourceCallback cb) {
this.cb = cb;
}
@Override
public void run() {
// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
// (b/136032534).
synchronized (cb.getLock()) {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
// Acquire for this particular callback.
engineResource.acquire();
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
}
void callCallbackOnResourceReady(ResourceCallback cb) {
try {
// This is overly broad, some Glide code is actually called here, but it's much
// simpler to encapsulate here than to do so at the actual call point in the
// Request implementation.
cb.onResourceReady(engineResource, dataSource, isLoadedFromAlternateCacheKey);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
上面代码中run()方法,首先用callCallbackOnResourceReady(cb)调用callback,然后调用removeCallback(cb)移除callback。callCallbackOnResourceReady()方法中调用cb.onResourceReady();其实cb就是SingleRequest。接着看SingleRequest.onResourceReady方法。
// SingleRequest
@Override
public void onResourceReady(
Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
stateVerifier.throwIfRecycled();
Resource<?> toRelease = null;
try {
synchronized (requestLock) {
loadStatus = null;
if (resource == null) {
GlideException exception =
new GlideException(
"Expected to receive a Resource<R> with an "
+ "object of "
+ transcodeClass
+ " inside, but instead got null.");
onLoadFailed(exception);
return;
}
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
toRelease = resource;
this.resource = null;
GlideException exception =
new GlideException(
"Expected to receive an object of "
+ transcodeClass
+ " but instead"
+ " got "
+ (received != null ? received.getClass() : "")
+ "{"
+ received
+ "} inside"
+ " "
+ "Resource{"
+ resource
+ "}."
+ (received != null
? ""
: " "
+ "To indicate failure return a null Resource "
+ "object, rather than a Resource object containing null data."));
onLoadFailed(exception);
return;
}
if (!canSetResource()) {
toRelease = resource;
this.resource = null;
// We can't put the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
// 重点方法
onResourceReady(
(Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
}
} finally {
if (toRelease != null) {
engine.release(toRelease);
}
}
}
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;
if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
+ dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
+ LogTime.getElapsedMillis(startTime) + " ms");
}
isCallingCallbacks = true;
try {
// 尝试调用各个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) {
// animationFactory默认为NoTransition.getFactory(),生成的animation为NO_ANIMATION
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
// target为DrawableImageViewTarget
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
// 通知requestCoordinator
notifyLoadSuccess();
}
DrawableImageViewTarget的基类ImageViewTarget实现了此方法:
// ImageViewTarget.java
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
// NO_ANIMATION.transition返回false,所以直接调用setResourceInternal方法
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
// Order matters here. Set the resource first to make sure that the Drawable has a valid and
// non-null Callback before starting it.
// 先设置图片
setResource(resource);
// 然后如果是动画,会执行动画
maybeUpdateAnimatable(resource);
}
private void maybeUpdateAnimatable(@Nullable Z resource) {
// BitmapDrawable显然不是一个Animatable对象,所以走else分支
if (resource instanceof Animatable) {
animatable = (Animatable) resource;
animatable.start();
} else {
animatable = null;
}
}
// DrawableImageViewTarget
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
至此网络图片已经通过view.setImageDrawable(resource)加载完毕。
into 流程图: