diff --git a/library/src/main/java/com/bumptech/glide/Glide.java b/library/src/main/java/com/bumptech/glide/Glide.java
index 4951007c00..67a0a85179 100644
--- a/library/src/main/java/com/bumptech/glide/Glide.java
+++ b/library/src/main/java/com/bumptech/glide/Glide.java
@@ -153,7 +153,7 @@ public static File getPhotoCacheDir(@NonNull Context context) {
* Returns a directory with the given name in the private cache directory of the application to
* use to store retrieved media and thumbnails.
*
- * @param context A context.
+ * @param context A context.
* @param cacheName The name of the subdirectory in which to store the cache.
* @see #getPhotoCacheDir(android.content.Context)
*/
@@ -181,13 +181,16 @@ public static File getPhotoCacheDir(@NonNull Context context, @NonNull String ca
*/
@NonNull
// Double checked locking is safe here.
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide
@SuppressWarnings("GuardedBy")
public static Glide get(@NonNull Context context) {
+ //双重检查锁DCL
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
+ //检查并初始化Glide
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
@@ -196,6 +199,7 @@ public static Glide get(@NonNull Context context) {
return glide;
}
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
@@ -207,14 +211,15 @@ private static void checkAndInitializeGlide(
+ " use the provided Glide instance instead");
}
isInitializing = true;
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide-初始化
initializeGlide(context, generatedAppGlideModule);
isInitializing = false;
}
/**
* @deprecated Use {@link #init(Context, GlideBuilder)} to get a singleton compatible with Glide's
- * generated API.
- *
This method will be removed in a future version of Glide.
+ * generated API.
+ *
This method will be removed in a future version of Glide.
*/
@VisibleForTesting
@Deprecated
@@ -260,12 +265,15 @@ public static void tearDown() {
}
}
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide-初始化
@GuardedBy("Glide.class")
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
+ //使用 GlideBuilder 建造者模式创建glide
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide-初始化
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
@@ -304,6 +312,7 @@ private static void initializeGlide(
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
+ //设置RequestManagerFactory工厂
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
@@ -311,6 +320,7 @@ private static void initializeGlide(
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide-建造者模式->build
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
@@ -372,6 +382,7 @@ private static void throwIncorrectGlideModule(Exception e) {
e);
}
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide-构造函数
@SuppressWarnings("PMD.UnusedFormalParameter")
Glide(
@NonNull Context context,
@@ -395,7 +406,7 @@ private static void throwIncorrectGlideModule(Exception e) {
this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;
final Resources resources = context.getResources();
-
+ //组件注册
registry = new Registry();
registry.register(new DefaultImageHeaderParser());
// Right now we're only using this parser for HEIF images, which are only supported on OMR1+.
@@ -412,6 +423,7 @@ private static void throwIncorrectGlideModule(Exception e) {
VideoDecoder.parcel(bitmapPool);
// TODO(judds): Make ParcelFileDescriptorBitmapDecoder work with ImageDecoder.
+ //文件,流等转Bitmap操作
Downsampler downsampler =
new Downsampler(
registry.getImageHeaderParsers(), resources.getDisplayMetrics(), bitmapPool, arrayPool);
@@ -443,10 +455,19 @@ private static void throwIncorrectGlideModule(Exception e) {
ContentResolver contentResolver = context.getContentResolver();
registry
+ //encoderRegistry
+ //byte写入文件File
.append(ByteBuffer.class, new ByteBufferEncoder())
+ //encoderRegistry
+ //将流写入磁盘的Encoder
.append(InputStream.class, new StreamEncoder(arrayPool))
+
/* Bitmaps */
+ //decoderRegistry
+ //byte->Bitmap
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
+ //decoderRegistry
+ //Stream->Bitmap
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder);
if (ParcelFileDescriptorRewinder.isSupported()) {
@@ -525,6 +546,7 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
}
registry
+ //用于从 Android 资源 ID 加载InputStream的工厂
.append(int.class, InputStream.class, resourceLoaderStreamFactory)
.append(int.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory)
.append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
@@ -533,8 +555,10 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
.append(int.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory)
.append(Integer.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory)
.append(int.class, Uri.class, resourceLoaderUriFactory)
+ //从Uri加载
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
.append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory())
+ //从String加载InputStream
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(
@@ -567,6 +591,7 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
.append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
.append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
.append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
+ //用于平移GlideUrl (HTTP / HTTPS URLS)到InputStream数据。
.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
.append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
.append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
@@ -592,8 +617,9 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, byteBufferVideoDecoder));
}
-
+ //创建了一个ImageViewTargetFactory
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
+ //创建了一个GlideContext对象
glideContext =
new GlideContext(
context,
@@ -636,7 +662,9 @@ public ArrayPool getArrayPool() {
return arrayPool;
}
- /** @return The context associated with this instance. */
+ /**
+ * @return The context associated with this instance.
+ */
@NonNull
public Context getContext() {
return glideContext.getBaseContext();
@@ -669,7 +697,7 @@ GlideContext getGlideContext() {
* every rotation.
*
* @param bitmapAttributeBuilders The list of {@link Builder Builders} representing individual
- * sizes and configurations of {@link Bitmap}s to be pre-filled.
+ * sizes and configurations of {@link Bitmap}s to be pre-filled.
*/
@SuppressWarnings("unused") // Public API
public synchronized void preFillBitmapPool(
@@ -731,7 +759,9 @@ public void clearDiskCache() {
engine.clearDiskCache();
}
- /** Internal method. */
+ /**
+ * Internal method.
+ */
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
@@ -762,6 +792,7 @@ public MemoryCategory setMemoryCategory(@NonNull MemoryCategory memoryCategory)
return oldCategory;
}
+ // TODO: Glide源码-Glide.with(context)--获取RequestManagerRetriever
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
@@ -771,6 +802,7 @@ private static RequestManagerRetriever getRetriever(@Nullable Context 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).");
+ // TODO: Glide源码-Glide.with(context)--获取单例Glide并且获取其对应的retriever
return Glide.get(context).getRequestManagerRetriever();
}
@@ -786,7 +818,8 @@ private static RequestManagerRetriever getRetriever(@Nullable Context context) {
* the same vein, if the resource will be used in a view in an activity, the load should be
* started with {@link #with(android.app.Activity)}}.
*
- *
This method is appropriate for resources that will be used outside of the normal fragment or
+ *
This method is appropriate for resources that will be used outside of the normal fragment
+ * or
* activity lifecycle (For example in services, or for notification thumbnails).
*
* @param context Any context, will not be retained.
@@ -796,6 +829,7 @@ private static RequestManagerRetriever getRetriever(@Nullable Context context) {
* @see #with(androidx.fragment.app.Fragment)
* @see #with(androidx.fragment.app.FragmentActivity)
*/
+ // TODO: Glide源码-Glide.with(context)返回RequestManager流程
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
@@ -808,15 +842,20 @@ public static RequestManager with(@NonNull Context context) {
* @param activity The activity to use.
* @return A RequestManager for the given activity that can be used to start a load.
*/
+
+ // TODO: Glide源码-Glide.with(context)--返回RequestManager流程
@NonNull
public static RequestManager with(@NonNull Activity activity) {
- return getRetriever(activity).get(activity);
+ // TODO: Glide源码-Glide.with(context)--获取RequestManagerRetriever,然后获取RequestManager
+ return getRetriever(activity)
+ // TODO: Glide源码-Glide.with(context)--调用RequestManagerRetriever.get()获取RequestManager
+ .get(activity);
}
/**
- * Begin a load with Glide that will tied to the give {@link
- * androidx.fragment.app.FragmentActivity}'s lifecycle and that uses the given {@link
- * androidx.fragment.app.FragmentActivity}'s default options.
+ * Begin a load with Glide that will tied to the give {@link androidx.fragment.app.FragmentActivity}'s
+ * lifecycle and that uses the given {@link androidx.fragment.app.FragmentActivity}'s default
+ * options.
*
* @param activity The activity to use.
* @return A RequestManager for the given FragmentActivity that can be used to start a load.
@@ -845,8 +884,7 @@ public static RequestManager with(@NonNull Fragment fragment) {
* @param fragment The fragment to use.
* @return A RequestManager for the given Fragment that can be used to start a load.
* @deprecated Prefer support Fragments and {@link #with(Fragment)} instead, {@link
- * android.app.Fragment} will be deprecated. See
- * https://github.com/android/android-ktx/pull/161#issuecomment-363270555.
+ * android.app.Fragment} will be deprecated. See https://github.com/android/android-ktx/pull/161#issuecomment-363270555.
*/
@SuppressWarnings("deprecation")
@Deprecated
@@ -935,10 +973,14 @@ public void onLowMemory() {
clearMemory();
}
- /** Creates a new instance of {@link RequestOptions}. */
+ /**
+ * Creates a new instance of {@link RequestOptions}.
+ */
public interface RequestOptionsFactory {
- /** Returns a non-null {@link RequestOptions} object. */
+ /**
+ * Returns a non-null {@link RequestOptions} object.
+ */
@NonNull
RequestOptions build();
}
diff --git a/library/src/main/java/com/bumptech/glide/GlideBuilder.java b/library/src/main/java/com/bumptech/glide/GlideBuilder.java
index 41373766ba..76ae5c7a97 100644
--- a/library/src/main/java/com/bumptech/glide/GlideBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/GlideBuilder.java
@@ -520,6 +520,7 @@ Glide build(@NonNull Context context) {
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
+ //TODO BitmapPool-图片缓存池
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
diff --git a/library/src/main/java/com/bumptech/glide/GlideContext.java b/library/src/main/java/com/bumptech/glide/GlideContext.java
index f312830b18..439a0258a8 100644
--- a/library/src/main/java/com/bumptech/glide/GlideContext.java
+++ b/library/src/main/java/com/bumptech/glide/GlideContext.java
@@ -97,6 +97,7 @@ public TransitionOptions, T> getDefaultTransitionOptions(@NonNull Class
@NonNull
public ViewTarget buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class transcodeClass) {
+ //构建ImageViewTarget
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
diff --git a/library/src/main/java/com/bumptech/glide/RequestBuilder.java b/library/src/main/java/com/bumptech/glide/RequestBuilder.java
index a592e119ac..36a511d6f2 100644
--- a/library/src/main/java/com/bumptech/glide/RequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/RequestBuilder.java
@@ -779,19 +779,23 @@ > Y into(
Executor callbackExecutor) {
return into(target, targetListener, /*options=*/ this, callbackExecutor);
}
-
+ // TODO: Glide源码-into流程
private > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener,
BaseRequestOptions> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
+ //这里的 isModelSet 是在 load 的时候赋值为 true 的,所以不会抛异常
+ //调用load设置modle后isModeSet为true
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
-
+ //构建Request target=DrawableImageViewTarget
+ //最终返回了SingleRequest子类
Request request = buildRequest(target, targetListener, options, callbackExecutor);
+ //下面的几行说明是否与上一个请求冲突,一般不用管 直接看下面 else 判断
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
@@ -807,9 +811,11 @@ private > Y into(
}
return target;
}
-
+ //清理掉目标请求管理
requestManager.clear(target);
+ //将request作为tag设置给imageview-在父类ViewTarget中设置的
target.setRequest(request);
+ //最后是调用 RequestManager 的 track 来执行目标的 Glide request 请求
requestManager.track(target, request);
return target;
@@ -836,10 +842,11 @@ private boolean isSkipMemoryCacheWithCompletePreviousRequest(
* ImageView}.
*/
@NonNull
+ // TODO: Glide源码-into流程
public ViewTarget into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
-
+ // 根据 ImageView 布局中的 scaleType 来重构 requestOptions
BaseRequestOptions> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
@@ -847,6 +854,7 @@ public ViewTarget into(@NonNull ImageView view) {
// 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.
+ //如果在 xml ImageView 节点中 没有设置 scaleType 那么默认在构造函数中进行了初始化为 mScaleType = ScaleType.FIT_CENTER;
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
@@ -868,11 +876,14 @@ public ViewTarget into(@NonNull ImageView view) {
// Do nothing.
}
}
-
+ //调用 into 重载函数,创建一个 ViewTarget
return into(
+ //调用 buildImageViewTarget 构建一个 ImageView 类型的 Target(Bitmap/Drawable(GifDrawable))
+ //这里我们使用Drawable.class 返回 DrawableImageViewTarget
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
+ //在主线程运动runnable的线程池
Executors.mainThreadExecutor());
}
@@ -1020,12 +1031,13 @@ private Priority getThumbnailPriority(@NonNull Priority current) {
throw new IllegalArgumentException("unknown priority: " + getPriority());
}
}
-
+ //构建Request
private Request buildRequest(
Target target,
@Nullable RequestListener targetListener,
BaseRequestOptions> requestOptions,
Executor callbackExecutor) {
+ //构建Request
return buildRequestRecursive(
/*requestLock=*/ new Object(),
target,
@@ -1057,7 +1069,7 @@ private Request buildRequestRecursive(
errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
-
+ //构建Request
Request mainRequest =
buildThumbnailRequestRecursive(
requestLock,
@@ -1097,7 +1109,7 @@ private Request buildRequestRecursive(
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
-
+ //构建Request
private Request buildThumbnailRequestRecursive(
Object requestLock,
Target target,
@@ -1109,6 +1121,7 @@ private Request buildThumbnailRequestRecursive(
int overrideHeight,
BaseRequestOptions> requestOptions,
Executor callbackExecutor) {
+ //缩略图,分支先不看
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
if (isThumbnailBuilt) {
@@ -1206,6 +1219,7 @@ private Request buildThumbnailRequestRecursive(
return coordinator;
} else {
// Base case: no thumbnail.
+ //构建Request
return obtainRequest(
requestLock,
target,
@@ -1219,7 +1233,7 @@ private Request buildThumbnailRequestRecursive(
callbackExecutor);
}
}
-
+ //构建Request
private Request obtainRequest(
Object requestLock,
Target target,
@@ -1231,6 +1245,7 @@ private Request obtainRequest(
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
+ //构建Request
return SingleRequest.obtain(
context,
glideContext,
diff --git a/library/src/main/java/com/bumptech/glide/RequestManager.java b/library/src/main/java/com/bumptech/glide/RequestManager.java
index a4d2319788..c11a1d66f3 100644
--- a/library/src/main/java/com/bumptech/glide/RequestManager.java
+++ b/library/src/main/java/com/bumptech/glide/RequestManager.java
@@ -56,6 +56,7 @@
*/
public class RequestManager
implements ComponentCallbacks2, LifecycleListener, ModelTypes> {
+
private static final RequestOptions DECODE_TYPE_BITMAP = decodeTypeOf(Bitmap.class).lock();
private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
private static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
@@ -94,7 +95,7 @@ public void run() {
private RequestOptions requestOptions;
private boolean pauseAllRequestsOnTrimMemoryModerate;
-
+ // TODO: Glide源码-Glide.with(context)-->RequestManager的创建
public RequestManager(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@@ -109,7 +110,7 @@ public RequestManager(
context);
}
- // Our usage is safe here.
+ // TODO: Glide源码-Glide.with(context)-->RequestManager的创建
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
@@ -133,17 +134,20 @@ public RequestManager(
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
+ //子线程通过主线程 post添加到lifecycle中
if (Util.isOnBackgroundThread()) {
Util.postOnUiThread(addSelfToLifecycle);
} else {
+ //将rm添加到lifecycle,该lifecycle在frag中
lifecycle.addListener(this);
}
+ //添加了一个网络变化监听
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
-
+ //最后将rm添加到glide的managers集合中--用于内存管理 ,onDestroy时,清除
glide.registerRequestManager(this);
}
@@ -169,8 +173,8 @@ private synchronized void updateRequestOptions(@NonNull RequestOptions toUpdate)
*
*
The modified options will only be applied to loads started after this method is called.
*
- * @see RequestBuilder#apply(BaseRequestOptions)
* @return This request manager.
+ * @see RequestBuilder#apply(BaseRequestOptions)
*/
@NonNull
public synchronized RequestManager applyDefaultRequestOptions(
@@ -191,8 +195,8 @@ public synchronized RequestManager applyDefaultRequestOptions(
* {@link RequestOptions} provided here. Instead the manager will create a clone of these options
* and mutate the clone.
*
- * @see #applyDefaultRequestOptions(RequestOptions)
* @return This request manager.
+ * @see #applyDefaultRequestOptions(RequestOptions)
*/
@NonNull
public synchronized RequestManager setDefaultRequestOptions(
@@ -251,6 +255,7 @@ public synchronized boolean isPaused() {
* @see #isPaused()
* @see #resumeRequests()
*/
+ // TODO Glide生命周期变化时调用-onStop()
public synchronized void pauseRequests() {
requestTracker.pauseRequests();
}
@@ -263,10 +268,9 @@ public synchronized void pauseRequests() {
* automatically resume onStart().
*
*
This will release the memory used by completed bitmaps but leaves them in any configured
- * caches. When an #{@link android.app.Activity} receives #{@link
- * android.app.Activity#onTrimMemory(int)} at a level of #{@link
- * android.content.ComponentCallbacks2#TRIM_MEMORY_BACKGROUND} this is desirable in order to keep
- * your process alive longer.
+ * caches. When an #{@link android.app.Activity} receives #{@link android.app.Activity#onTrimMemory(int)}
+ * at a level of #{@link android.content.ComponentCallbacks2#TRIM_MEMORY_BACKGROUND} this is
+ * desirable in order to keep your process alive longer.
*
* @see #isPaused()
* @see #resumeRequests()
@@ -320,6 +324,8 @@ public synchronized void pauseRequestsRecursive() {
* @see #isPaused()
* @see #pauseRequests()
*/
+ // TODO Glide生命周期变化时调用-onStart()
+
public synchronized void resumeRequests() {
requestTracker.resumeRequests();
}
@@ -344,9 +350,12 @@ public synchronized void resumeRequestsRecursive() {
* android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused
* requests.
*/
+ // TODO Glide生命周期变化时调用-onStart()
@Override
public synchronized void onStart() {
+ //开始请求
resumeRequests();
+ //开启动画用
targetTracker.onStart();
}
@@ -354,9 +363,12 @@ public synchronized void onStart() {
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
+ // TODO Glide生命周期变化时调用-onStop()
@Override
public synchronized void onStop() {
+ //停止
pauseRequests();
+ //停止动画用
targetTracker.onStop();
}
@@ -364,17 +376,22 @@ public synchronized void onStop() {
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
+ // TODO Glide生命周期变化时调用-onDestroy()
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target> target : targetTracker.getAll()) {
+ //clear每个target,会调用request.clear()
clear(target);
}
targetTracker.clear();
+ //从Requests中移除request,也,会调用request.clear()
requestTracker.clearRequests();
+ //移除监听
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
Util.removeCallbacksOnUiThread(addSelfToLifecycle);
+ //glide移除RequestManager
glide.unregisterRequestManager(this);
}
@@ -385,14 +402,14 @@ public synchronized void onDestroy() {
* @return A new request builder for loading a {@link android.graphics.Bitmap}
*/
@NonNull
+ // TODO: Glide源码-load:先.asBitmap()再.load("url")-使用Bitmap的RequestOptions
@CheckResult
public RequestBuilder asBitmap() {
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}
/**
- * Attempts to always load the resource as a {@link
- * com.bumptech.glide.load.resource.gif.GifDrawable}.
+ * Attempts to always load the resource as a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
*
*
If the underlying data is not a GIF, this will fail. As a result, this should only be used
* if the model represents an animated GIF and the caller wants to interact with the GifDrawable
@@ -400,11 +417,11 @@ public RequestBuilder asBitmap() {
* whether or not the given data represents an animated GIF and return the appropriate {@link
* Drawable}, animated or not, automatically.
*
- * @return A new request builder for loading a {@link
- * com.bumptech.glide.load.resource.gif.GifDrawable}.
+ * @return A new request builder for loading a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
*/
@NonNull
@CheckResult
+ // TODO: Glide源码-load:先.asGif()再.load("url")-使用GifDrawable的RequestOptions
public RequestBuilder asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}
@@ -422,6 +439,7 @@ public RequestBuilder asGif() {
@NonNull
@CheckResult
public RequestBuilder asDrawable() {
+ // TODO: Glide源码-load--创建RequestBuilder
return as(Drawable.class);
}
@@ -456,9 +474,13 @@ public RequestBuilder load(@Nullable Drawable drawable) {
*/
@NonNull
@CheckResult
+ // TODO: Glide源码-load:默认Drawable-使用默认的 new RequestOptions
@Override
public RequestBuilder load(@Nullable String string) {
- return asDrawable().load(string);
+// TODO: Glide源码-load--创建RequestBuilder-默认情况使用asDrawable()
+ return asDrawable()
+ //设置 model
+ .load(string);
}
/**
@@ -542,7 +564,8 @@ public RequestBuilder load(@Nullable Object model) {
*
*
This method is designed to work for remote data that is or will be cached using {@link
* com.bumptech.glide.load.engine.DiskCacheStrategy#DATA}. As a result, specifying a {@link
- * com.bumptech.glide.load.engine.DiskCacheStrategy} on this request is generally not recommended.
+ * com.bumptech.glide.load.engine.DiskCacheStrategy} on this request is generally not
+ * recommended.
*
* @return A new request builder for downloading content to cache and returning the cache File.
*/
@@ -580,9 +603,8 @@ public RequestBuilder asFile() {
}
/**
- * Attempts to load the resource using any registered {@link
- * com.bumptech.glide.load.ResourceDecoder}s that can decode the given resource class or any
- * subclass of the given resource class.
+ * Attempts to load the resource using any registered {@link com.bumptech.glide.load.ResourceDecoder}s
+ * that can decode the given resource class or any subclass of the given resource class.
*
* @param resourceClass The resource to decode.
* @return A new request builder for loading the given resource class.
@@ -591,6 +613,7 @@ public RequestBuilder asFile() {
@CheckResult
public RequestBuilder as(
@NonNull Class resourceClass) {
+ // TODO: Glide源码-load--创建RequestBuilder-传入glide,rm,context,resourceClass(drawable,bitmap,GifDrawable,File)
return new RequestBuilder<>(glide, this, resourceClass, context);
}
@@ -603,7 +626,7 @@ public RequestBuilder as(
*
* @param view The view to cancel loads and free resources for.
* @throws IllegalArgumentException if an object other than Glide's metadata is put as the view's
- * tag.
+ * tag.
* @see #clear(Target)
*/
public void clear(@NonNull View view) {
@@ -616,6 +639,7 @@ public void clear(@NonNull View view) {
*
* @param target The Target to cancel loads for.
*/
+ // TODO Glide生命周期变化时调用-onDestroy()
public void clear(@Nullable final Target> target) {
if (target == null) {
return;
@@ -623,7 +647,7 @@ public void clear(@Nullable final Target> target) {
untrackOrDelegate(target);
}
-
+ // TODO Glide生命周期变化时调用-onDestroy()
private void untrackOrDelegate(@NonNull Target> target) {
boolean isOwnedByUs = untrack(target);
// We'll end up here if the Target was cleared after the RequestManager that started the request
@@ -646,6 +670,7 @@ private void untrackOrDelegate(@NonNull Target> target) {
Request request = target.getRequest();
if (!isOwnedByUs && !glide.removeFromManagers(target) && request != null) {
target.setRequest(null);
+ //调用request.clear(),和Stop流程一致
request.clear();
}
}
@@ -658,16 +683,20 @@ synchronized boolean untrack(@NonNull Target> target) {
}
if (requestTracker.clearAndRemove(request)) {
+ //target移除
targetTracker.untrack(target);
+ //target移除request,imageview的Tag设置为null
target.setRequest(null);
return true;
} else {
return false;
}
}
-
+ // TODO: Glide源码-into流程
synchronized void track(@NonNull Target> target, @NonNull Request request) {
+ //添加一个目标任务
targetTracker.track(target);
+ //执行 Glide request
requestTracker.runRequest(request);
}
diff --git a/library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java b/library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java
index 5602c1498c..364ef06f13 100644
--- a/library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java
+++ b/library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java
@@ -49,13 +49,15 @@ public HttpUrlFetcher(GlideUrl glideUrl, int timeout) {
this.timeout = timeout;
this.connectionFactory = connectionFactory;
}
-
+ // TODO: Glide源码-into流程
@Override
public void loadData(
@NonNull Priority priority, @NonNull DataCallback super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
+ //http 请求,返回一个 InputStream 输入流
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
+ //将 InputStream 以回调形式回调出去-->SourceGenerator#startNextLoad方法中的DataCallback
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/DataCacheGenerator.java b/library/src/main/java/com/bumptech/glide/load/engine/DataCacheGenerator.java
index 939ef09c14..0dc1aa5dd4 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/DataCacheGenerator.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/DataCacheGenerator.java
@@ -43,6 +43,7 @@ class DataCacheGenerator implements DataFetcherGenerator, DataFetcher.DataCallba
}
@Override
+ // TODO: Glide源码-into流程
public boolean startNext() {
GlideTrace.beginSection("DataCacheGenerator.startNext");
try {
@@ -57,6 +58,7 @@ public boolean startNext() {
// and the actions it performs are much more expensive than a single allocation.
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
+ //从磁盘缓存中获取
cacheFile = helper.getDiskCache().get(originalKey);
if (cacheFile != null) {
this.sourceKey = sourceId;
@@ -74,6 +76,7 @@ public boolean startNext() {
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
+ //从File转换成Stream--FileOpener
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/DecodeJob.java b/library/src/main/java/com/bumptech/glide/load/engine/DecodeJob.java
index 74cfc90e9b..0bb500caaa 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/DecodeJob.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/DecodeJob.java
@@ -33,13 +33,13 @@
*
Note: this class has a natural ordering that is inconsistent with equals.
*
* @param The type of resource that will be transcoded from the decoded and transformed
- * resource.
+ * resource.
*/
class DecodeJob
implements DataFetcherGenerator.FetcherReadyCallback,
- Runnable,
- Comparable>,
- Poolable {
+ Runnable,
+ Comparable>,
+ Poolable {
private static final String TAG = "DecodeJob";
private final DecodeHelper decodeHelper = new DecodeHelper<>();
@@ -145,7 +145,7 @@ boolean willDecodeFromCache() {
* Called when this object is no longer in use externally.
*
* @param isRemovedFromQueue {@code true} if we've been removed from the queue and {@link #run} is
- * neither in progress nor will ever be called again.
+ * neither in progress nor will ever be called again.
*/
void release(boolean isRemovedFromQueue) {
if (releaseManager.release(isRemovedFromQueue)) {
@@ -163,7 +163,9 @@ private void onEncodeComplete() {
}
}
- /** Called when the load has failed due to a an error or a series of errors. */
+ /**
+ * Called when the load has failed due to a an error or a series of errors.
+ */
private void onLoadFailed() {
if (releaseManager.onFailed()) {
releaseInternal();
@@ -219,6 +221,7 @@ public void cancel() {
// We need to rethrow only CallbackException, but not other types of Throwables.
@SuppressWarnings("PMD.AvoidRethrowingException")
@Override
+ // TODO: Glide源码-into流程
public void run() {
// This should be much more fine grained, but since Java's thread pool implementation silently
// swallows all otherwise fatal exceptions, this will at least make it obvious to developers
@@ -228,10 +231,12 @@ public void run() {
// ensure that the fetcher is cleaned up either way.
DataFetcher> localFetcher = currentFetcher;
try {
+ //是否取消了当前请求
if (isCancelled) {
notifyFailed();
return;
}
+ //执行
runWrapped();
} catch (CallbackException e) {
// If a callback not controlled by Glide throws an exception, we should avoid the Glide
@@ -269,13 +274,18 @@ public void run() {
}
}
+ // TODO: Glide源码-into流程
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
+ //循环取RESOURCE_CACHE,DATA_CACHE和SOURCE
stage = getNextStage(Stage.INITIALIZE);
+ //对应的ResourceCacheGenerator(资源转换后的磁盘缓存),DataCacheGenerator(原始数据的磁盘缓存),SourceGenerator
currentGenerator = getNextGenerator();
+ //执行 Generator
runGenerators();
break;
+ //切换线程池后重新执行这里
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
@@ -302,16 +312,23 @@ private DataFetcherGenerator getNextGenerator() {
}
}
+ // TODO: Glide源码-into流程
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
+ //判断是否取消,是否开始
+ //调用 Generator.startNext() 判断是否是属于开始执行的任务
while (!isCancelled
&& currentGenerator != null
+ //currentGenerator.startNext()返回true代表命中Generator
&& !(isStarted = currentGenerator.startNext())) {
+ //如果没有命中,则下一状态
stage = getNextStage(stage);
+ //获取下个Generator继续判断是否命中
currentGenerator = getNextGenerator();
+ //磁盘缓存没有命中的话直接从网络上获取
if (stage == Stage.SOURCE) {
reschedule();
return;
@@ -333,9 +350,11 @@ private void notifyFailed() {
onLoadFailed();
}
+ // TODO: Glide源码-into流程
private void notifyComplete(
Resource resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
setNotifiedOrThrow();
+ // 在 DecodeJob 的构建中, 我们知道这个 Callback 是 EngineJob
callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
}
@@ -369,28 +388,32 @@ private Stage getNextStage(Stage current) {
}
}
+ // TODO: Glide源码-into流程
@Override
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
+ //这里切换线程池重新执行任务
callback.reschedule(this);
}
+ // TODO: Glide源码-into流程-从SourceGenerator回调回来
@Override
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher> fetcher, DataSource dataSource, Key attemptedKey) {
- this.currentSourceKey = sourceKey;
- this.currentData = data;
- this.currentFetcher = fetcher;
- this.currentDataSource = dataSource;
+ this.currentSourceKey = sourceKey;//当前返回数据的 key
+ this.currentData = data;//返回的数据
+ this.currentFetcher = fetcher;//返回的数据执行器,这里可以理解为 HttpUrlFetcher
+ this.currentDataSource = dataSource;//数据来源 url
this.currentAttemptingKey = attemptedKey;
this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);
-
+ //线程不一致时切换线程池重新执行DecodeJob的run()方法再调用 decodeFromRetrievedData()方法。
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
+ //解析返回回来的数据
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
@@ -413,6 +436,7 @@ public void onDataFetcherFailed(
}
}
+ // TODO: Glide源码-into流程--返回数据
private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey(
@@ -427,11 +451,13 @@ private void decodeFromRetrievedData() {
}
Resource resource = null;
try {
+ // 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream , DataSource.REMOTE
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
+ //解析完成后,通知下去
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);
} else {
@@ -439,6 +465,7 @@ private void decodeFromRetrievedData() {
}
}
+ // TODO: Glide源码-into流程
private void notifyEncodeAndRelease(
Resource resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease");
@@ -453,11 +480,12 @@ private void notifyEncodeAndRelease(
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
-
+ //通知调用层数据已经装备好了
notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);
stage = Stage.ENCODE;
try {
+ //这里就是Resource磁盘缓存
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
@@ -469,12 +497,14 @@ private void notifyEncodeAndRelease(
// Call onEncodeComplete outside the finally block so that it's not called if the encode
// process
// throws.
+ //完成
onEncodeComplete();
} finally {
GlideTrace.endSection();
}
}
+ // TODO: Glide源码-into流程-解析资源
private Resource decodeFromData(
DataFetcher> fetcher, Data data, DataSource dataSource) throws GlideException {
try {
@@ -482,6 +512,7 @@ private Resource decodeFromData(
return null;
}
long startTime = LogTime.getLogTime();
+ //解析
Resource result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
@@ -493,9 +524,12 @@ private Resource decodeFromData(
}
@SuppressWarnings("unchecked")
+ // TODO: Glide源码-into流程-解析资源
private Resource decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
+ //获取当前数据类的解析器 LoadPath
LoadPath path = decodeHelper.getLoadPath((Class) data.getClass());
+ //通过 LoadPath 解析器来解析数据
return runLoadPath(data, dataSource, path);
}
@@ -525,13 +559,16 @@ private Options getOptionsWithHardwareConfig(DataSource dataSource) {
return options;
}
+ // TODO: Glide源码-into流程-解析资源
private Resource runLoadPath(
Data data, DataSource dataSource, LoadPath path)
throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
+ //因为这里返回的是一个 InputStream 所以 这里拿到的是 InputStreamRewinder
DataRewinder rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
+ //将解析资源的任务转移到 Load.path 方法中
return path.load(
rewinder, options, width, height, new DecodeCallback(dataSource));
} finally {
@@ -564,13 +601,16 @@ public StateVerifier getVerifier() {
@Synthetic
@NonNull
+ // TODO: Glide源码-into流程-回调
Resource onResourceDecoded(DataSource dataSource, @NonNull Resource decoded) {
@SuppressWarnings("unchecked")
Class resourceSubClass = (Class) decoded.get().getClass();
Transformation appliedTransformation = null;
Resource transformed = decoded;
+ //如果不是Resource缓存
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
+ //执行 transform
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
// TODO: Make this the responsibility of the Transformation.
@@ -590,6 +630,7 @@ Resource onResourceDecoded(DataSource dataSource, @NonNull Resource de
Resource result = transformed;
boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
+ //是否Resource磁盘缓存
if (diskCacheStrategy.isResourceCacheable(
isFromAlternateCacheKey, dataSource, encodeStrategy)) {
if (encoder == null) {
@@ -634,6 +675,7 @@ private final class DecodeCallback implements DecodePath.DecodeCallback {
@NonNull
@Override
+ // TODO: Glide源码-into流程-回调
public Resource onResourceDecoded(@NonNull Resource decoded) {
return DecodeJob.this.onResourceDecoded(dataSource, decoded);
}
@@ -699,6 +741,7 @@ void init(Key key, ResourceEncoder encoder, LockedResource toEncode) {
void encode(DiskCacheProvider diskCacheProvider, Options options) {
GlideTrace.beginSection("DecodeJob.encode");
try {
+ //磁盘缓存
diskCacheProvider
.getDiskCache()
.put(key, new DataCacheWriter<>(encoder, toEncode, options));
@@ -733,11 +776,17 @@ interface DiskCacheProvider {
DiskCache getDiskCache();
}
- /** Why we're being executed again. */
+ /**
+ * Why we're being executed again.
+ */
private enum RunReason {
- /** The first time we've been submitted. */
+ /**
+ * The first time we've been submitted.
+ */
INITIALIZE,
- /** We want to switch from the disk cache service to the source executor. */
+ /**
+ * We want to switch from the disk cache service to the source executor.
+ */
SWITCH_TO_SOURCE_SERVICE,
/**
* We retrieved some data on a thread we don't own and want to switch back to our thread to
@@ -746,19 +795,33 @@ private enum RunReason {
DECODE_DATA,
}
- /** Where we're trying to decode data from. */
+ /**
+ * Where we're trying to decode data from.
+ */
private enum Stage {
- /** The initial stage. */
+ /**
+ * The initial stage.
+ */
INITIALIZE,
- /** Decode from a cached resource. */
+ /**
+ * Decode from a cached resource.
+ */
RESOURCE_CACHE,
- /** Decode from cached source data. */
+ /**
+ * Decode from cached source data.
+ */
DATA_CACHE,
- /** Decode from retrieved source. */
+ /**
+ * Decode from retrieved source.
+ */
SOURCE,
- /** Encoding transformed resources after a successful load. */
+ /**
+ * Encoding transformed resources after a successful load.
+ */
ENCODE,
- /** No more viable stages. */
+ /**
+ * No more viable stages.
+ */
FINISHED,
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/DecodePath.java b/library/src/main/java/com/bumptech/glide/load/engine/DecodePath.java
index 8fe172fde8..dc27ac6e4c 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/DecodePath.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/DecodePath.java
@@ -48,7 +48,7 @@ public DecodePath(
+ transcodeClass.getSimpleName()
+ "}";
}
-
+ // TODO: Glide源码-into流程-解析资源
public Resource decode(
DataRewinder rewinder,
int width,
@@ -56,12 +56,16 @@ public Resource decode(
@NonNull Options options,
DecodeCallback callback)
throws GlideException {
+ //调用 decodeResource 将数据解析成中间资源
Resource decoded = decodeResource(rewinder, width, height, options);
+ //解析完数据回调出去DecodeJob
Resource transformed = callback.onResourceDecoded(decoded);
+ //转换资源为目标资源BitmapDrawableTranscoder--最后往上返回到DecodeJob#decodeFromRetrievedData 方法中
return transcoder.transcode(transformed, options);
}
@NonNull
+ // TODO: Glide源码-into流程-解析资源
private Resource decodeResource(
DataRewinder rewinder, int width, int height, @NonNull Options options)
throws GlideException {
@@ -74,6 +78,7 @@ private Resource decodeResource(
}
@NonNull
+ // TODO: Glide源码-into流程-解析资源
private Resource decodeResourceWithList(
DataRewinder rewinder,
int width,
@@ -89,6 +94,8 @@ private Resource decodeResourceWithList(
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
+ //如果从磁盘缓存调用
+ // 调用 StreamBitmapDecoder.decode 解析数据 StreamBitmapDecoder
result = decoder.decode(data, width, height, options);
}
// Some decoders throw unexpectedly. If they do, we shouldn't fail the entire load path, but
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/Engine.java b/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
index c469e967f5..cacb9dca83 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
@@ -152,6 +152,7 @@ public Engine(
* @param height The target height in pixels of the desired resource.
* @param cb The callback that will be called when the load completes.
*/
+ // TODO: Glide源码-into流程
public LoadStatus load(
GlideContext glideContext,
Object model,
@@ -173,7 +174,7 @@ public LoadStatus load(
ResourceCallback cb,
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
-
+ //构建key,用于缓存策略和请求
EngineKey key =
keyFactory.buildKey(
model,
@@ -187,9 +188,11 @@ public LoadStatus load(
EngineResource> memoryResource;
synchronized (this) {
+ //根据 key 拿到活动缓存,内存缓存中的资源
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
+ //等待现有工作或开始新工作
return waitForExistingOrStartNewJob(
glideContext,
model,
@@ -215,13 +218,13 @@ public LoadStatus load(
}
}
- // Avoid calling back while holding the engine lock, doing so makes it easier for callers to
- // deadlock.
+ // 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;
}
-
+ // TODO: Glide源码-into流程
private LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
@@ -244,9 +247,10 @@ private LoadStatus waitForExistingOrStartNewJob(
Executor callbackExecutor,
EngineKey key,
long startTime) {
-
+ //根据 Key 看看缓存中是否正在执行
EngineJob> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
+ //如果正在执行,把数据回调出去
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
@@ -254,6 +258,8 @@ private LoadStatus waitForExistingOrStartNewJob(
return new LoadStatus(cb, current);
}
+ // -------------- 走到这里说明是一个新的任务 ---------------
+ // -------------- 构建新的请求任务 ---------------
EngineJob engineJob =
engineJobFactory.build(
key,
@@ -261,7 +267,7 @@ private LoadStatus waitForExistingOrStartNewJob(
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
-
+ //构造decodeJob实现了runnable,放到engineJob中执行
DecodeJob decodeJob =
decodeJobFactory.build(
glideContext,
@@ -280,10 +286,11 @@ private LoadStatus waitForExistingOrStartNewJob(
onlyRetrieveFromCache,
options,
engineJob);
-
+ //把当前需要执行的引擎工作添加到集合中
jobs.put(key, engineJob);
-
+ //添加回调
engineJob.addCallback(cb, callbackExecutor);
+ //开始执行。
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
@@ -292,13 +299,14 @@ private LoadStatus waitForExistingOrStartNewJob(
return new LoadStatus(cb, engineJob);
}
+ // TODO: Glide源码-into流程
@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) {
@@ -306,7 +314,7 @@ private EngineResource> loadFromMemory(
}
return active;
}
-
+ // 从内存缓存中获取资源--如果内存缓存中有取出并从内存缓存中删除,放入活动缓存
EngineResource> cached = loadFromCache(key);
if (cached != null) {
if (VERBOSE_IS_LOGGABLE) {
@@ -333,9 +341,12 @@ private EngineResource> loadFromActiveResources(Key key) {
}
private EngineResource> loadFromCache(Key key) {
+ //从内存中取出,调用的remove方法
EngineResource> cached = getEngineResourceFromCache(key);
if (cached != null) {
+ //引用计数++
cached.acquire();
+ //放入活动缓存
activeResources.activate(key, cached);
}
return cached;
@@ -357,9 +368,10 @@ private EngineResource> getEngineResourceFromCache(Key key) {
}
return result;
}
-
+ // TODO Glide生命周期变化时调用-onStop()
public void release(Resource> resource) {
if (resource instanceof EngineResource) {
+ //活动到内存
((EngineResource>) resource).release();
} else {
throw new IllegalArgumentException("Cannot release anything but an EngineResource");
@@ -368,13 +380,15 @@ public void release(Resource> resource) {
@SuppressWarnings("unchecked")
@Override
+ // TODO: Glide源码-into流程
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);
}
@@ -390,12 +404,17 @@ public void onResourceRemoved(@NonNull final Resource> resource) {
resourceRecycler.recycle(resource, /*forceNextFrame=*/ true);
}
+ // TODO Glide生命周期变化时调用-onStop()
@Override
public void onResourceReleased(Key cacheKey, EngineResource> resource) {
+ //活动缓存删除
activeResources.deactivate(cacheKey);
+ //支持内存缓存
if (resource.isMemoryCacheable()) {
+ //放入内存缓存
cache.put(cacheKey, resource);
} else {
+ //不支持的话,释放
resourceRecycler.recycle(resource, /*forceNextFrame=*/ false);
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java b/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java
index 33151e0746..41a9aa9458 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java
@@ -124,11 +124,18 @@ synchronized EngineJob init(
this.onlyRetrieveFromCache = onlyRetrieveFromCache;
return this;
}
-
+ // TODO: Glide源码-into流程
public synchronized void start(DecodeJob decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
+ //RESOURCE_CACHE或DATA_CACHE使用diskCacheExecutor 本地缓存线程池
+ //否则使用ActiveSourceExecutor
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
+ //开始执行
+ /**
+ * 通过 DecodeJob 源码得知,它是实现的 Runnable 接口,这里 GlideExecutor 线程池开始执行,
+ * 就会启动 DecodeJob 的 run 函数,我们跟踪 run 的实现。
+ */
executor.execute(decodeJob);
}
@@ -151,11 +158,13 @@ synchronized void addCallback(final ResourceCallback cb, Executor callbackExecut
@SuppressWarnings("WeakerAccess")
@Synthetic
@GuardedBy("this")
+ // TODO: Glide源码-into流程
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.
+ //回调给 SingleRequest
cb.onResourceReady(engineResource, dataSource, isLoadedFromAlternateCacheKey);
} catch (Throwable t) {
throw new CallbackException(t);
@@ -225,6 +234,7 @@ private boolean isDone() {
"PMD.AvoidInstantiatingObjectsInLoops",
"PMD.AccessorMethodGeneration"
})
+ // TODO: Glide源码-into流程
@Synthetic
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
@@ -248,6 +258,7 @@ void notifyCallbacksOfResult() {
// middle of notifying if it synchronously released by one of the callbacks. Acquire it under
// a lock here so that any newly added callback that executes before the next locked section
// below can't recycle the resource before we call the callbacks.
+ //hasResource标为true
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
@@ -255,10 +266,11 @@ void notifyCallbacksOfResult() {
localKey = key;
localResource = engineResource;
}
-
+ //回调上层 Engine 任务完成了
engineJobListener.onEngineJobComplete(this, localKey, localResource);
-
+ //遍历资源回调给 ImageViewTarget
for (final ResourceCallbackAndExecutor entry : copy) {
+ //进入CallResourceReady的run
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
@@ -314,6 +326,7 @@ private synchronized void release() {
}
@Override
+ // TODO: Glide源码-into流程
public void onResourceReady(
Resource resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
synchronized (this) {
@@ -321,6 +334,7 @@ public void onResourceReady(
this.dataSource = dataSource;
this.isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey;
}
+ //这
notifyCallbacksOfResult();
}
@@ -333,6 +347,7 @@ public void onLoadFailed(GlideException e) {
}
@Override
+ // TODO: Glide源码-into流程
public void reschedule(DecodeJob> job) {
// Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself
// up.
@@ -417,6 +432,7 @@ private class CallResourceReady implements Runnable {
}
@Override
+ // TODO: Glide源码-into流程
public void run() {
// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
// (b/136032534).
@@ -425,6 +441,7 @@ public void run() {
if (cbs.contains(cb)) {
// Acquire for this particular callback.
engineResource.acquire();
+ //返回准备好的资源
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/EngineResource.java b/library/src/main/java/com/bumptech/glide/load/engine/EngineResource.java
index 1bbc821a46..6138d89248 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/EngineResource.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/EngineResource.java
@@ -102,17 +102,20 @@ synchronized void acquire() {
*/
// listener is effectively final.
@SuppressWarnings("SynchronizeOnNonFinalField")
+ // TODO Glide生命周期变化时调用-onStop()
void release() {
boolean release = false;
synchronized (this) {
if (acquired <= 0) {
throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
}
+ //为0表示活动缓存没有使用的地方了
if (--acquired == 0) {
release = true;
}
}
if (release) {
+ //活动到内存
listener.onResourceReleased(key, this);
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/LoadPath.java b/library/src/main/java/com/bumptech/glide/load/engine/LoadPath.java
index d3003642d8..1d71b11633 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/LoadPath.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/LoadPath.java
@@ -44,7 +44,7 @@ public LoadPath(
+ transcodeClass.getSimpleName()
+ "}";
}
-
+ // TODO: Glide源码-into流程-解析资源
public Resource load(
DataRewinder rewinder,
@NonNull Options options,
@@ -54,12 +54,13 @@ public Resource load(
throws GlideException {
List throwables = Preconditions.checkNotNull(listPool.acquire());
try {
+ //这里
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
listPool.release(throwables);
}
}
-
+ // TODO: Glide源码-into流程-解析资源
private Resource loadWithExceptionList(
DataRewinder rewinder,
@NonNull Options options,
@@ -70,9 +71,11 @@ private Resource loadWithExceptionList(
throws GlideException {
Resource result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
+ //遍历内部存储的 DecodePath 集合,通过他们来解析数据
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath path = decodePaths.get(i);
try {
+ //这里才是真正解析数据的地方
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/ResourceCacheGenerator.java b/library/src/main/java/com/bumptech/glide/load/engine/ResourceCacheGenerator.java
index 425d19e0d6..22a1639da0 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/ResourceCacheGenerator.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/ResourceCacheGenerator.java
@@ -41,6 +41,7 @@ class ResourceCacheGenerator implements DataFetcherGenerator, DataFetcher.DataCa
// See TODO below.
@SuppressWarnings("PMD.CollapsibleIfStatements")
@Override
+ // TODO: Glide源码-into流程
public boolean startNext() {
GlideTrace.beginSection("ResourceCacheGenerator.startNext");
try {
@@ -85,9 +86,11 @@ public boolean startNext() {
transformation,
resourceClass,
helper.getOptions());
+ //从磁盘缓存中获取
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
+ //根据文件类型从注册组件里获取类型加载器
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/ResourceRecycler.java b/library/src/main/java/com/bumptech/glide/load/engine/ResourceRecycler.java
index ed26e67ca4..81a2a367e1 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/ResourceRecycler.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/ResourceRecycler.java
@@ -11,14 +11,17 @@ class ResourceRecycler {
private final Handler handler =
new Handler(Looper.getMainLooper(), new ResourceRecyclerCallback());
+ // TODO Glide生命周期变化时调用-onStop()
synchronized void recycle(Resource> resource, boolean forceNextFrame) {
+ //正在释放或有子资源,发送handler进行释放
if (isRecycling || forceNextFrame) {
- // If a resource has sub-resources, releasing a sub resource can cause it's parent to be
+ // If a resource has sub-resources, releasing a sub resource can cause it's parent to be synchronously evicted which leads to a recycle loop when the parent releases it's children.
// synchronously evicted which leads to a recycle loop when the parent releases it's children.
// Posting breaks this loop.
handler.obtainMessage(ResourceRecyclerCallback.RECYCLE_RESOURCE, resource).sendToTarget();
} else {
isRecycling = true;
+ //释放-bitmap的话使用BitmapResource放在BitmapPool
resource.recycle();
isRecycling = false;
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/SourceGenerator.java b/library/src/main/java/com/bumptech/glide/load/engine/SourceGenerator.java
index 5273df49d0..7533e00e3b 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/SourceGenerator.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/SourceGenerator.java
@@ -22,8 +22,8 @@
* using registered {@link com.bumptech.glide.load.model.ModelLoader ModelLoaders} and the model
* provided for the load.
*
- *
Depending on the disk cache strategy, source data may first be written to disk and then loaded
- * from the cache file rather than returned directly.
+ *
Depending on the disk cache strategy, source data may first be written to disk and then
+ * loaded from the cache file rather than returned directly.
*
*
This object may be used by multiple threads, but only one at a time. It is not safe to access
* this object on multiple threads concurrently.
@@ -48,15 +48,19 @@ class SourceGenerator implements DataFetcherGenerator, DataFetcherGenerator.Fetc
// Concurrent access isn't supported.
@SuppressWarnings({"NonAtomicOperationOnVolatileField", "NonAtomicVolatileUpdate"})
@Override
+ // TODO: Glide源码-into流程
public boolean startNext() {
+ //重新走进来后进行缓存
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
try {
+ //写入磁盘缓存
boolean isDataInCache = cacheData(data);
// If we failed to write the data to cache, the cacheData method will try to decode the
// original data directly instead of going through the disk cache. Since cacheData has
// already called our callback at this point, there's nothing more to do but return.
+ //这里在cacheData()中写入磁盘失败的时候通过DecodeJob.onDataFetcherReady()回调出去了,按命中返回true
if (!isDataInCache) {
return true;
}
@@ -71,7 +75,7 @@ public boolean startNext() {
}
}
}
-
+ //写入磁盘缓存成功后,执行DataCacheGenerator.startNext()策略,如果命中这里也返回true,表示命中
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
@@ -79,22 +83,28 @@ public boolean startNext() {
loadData = null;
boolean started = false;
+ //循环加载器
while (!started && hasNextModelLoader()) {
+ //获取一个 ModelLoad 加载器--这里是 HttpGlideUrlLoader.buildLoadData获取
+ //new LoadData<>(url, new HttpUrlFetcher(url, timeout))
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
- || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
+ || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
startNextLoad(loadData);
}
}
+ //否则返回false表示未命中
return started;
}
private void startNextLoad(final LoadData> toStart) {
+ //使用加载器中的 fetcher 根据优先级加载数据HttpUrlFetcher->loadData()方法
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback