文章篇幅较多.建议配合源码阅读并且有空闲时间去理解
Glide基本使用
RequestOptions options = new RequestOptions()
.placeholder(R.mipmap.ic_launcher) //占位图
.error(R.mipmap.ic_launcher)//加载失败图
.circleCrop();//圆形
Glide.with(this) //初始化Glide Glide的生命周期
.load(beans.get(0).getData().get(position).getImagePath())//图片地址
.apply(options) //添加请求的参数
.centerCrop()//图片加载样式
.into(imageView);//加载的View
基本概念
- Model 类型
- Data 输入流
- Resource 解码后资源
- TransformedResource 转换后的资源
- TranscodedResource 转码完成后的资源
- Target 显示目标
with方法
传入的context
对象表示当前Glide
的加载生命周期,如果传入Activity
时调用onDestroy
方法当前Glide
加载的图片就会销毁
- 得到一个
RequestManager
主要用来控制整个界面的生命周期 -
RequestManagerRetriever
是用来生产RequestManager
的 -
RequestManagerFragment
无界面的Fragment
用来绑定生命周期
public static RequestManager with(@NonNull Context context) {
//返回一个RequestManagerRetriever象
// 获取一个 RequestManagerRetriever 描述一个图片加载请求的管理者
return getRetriever(context).get(context);
}
//
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
//...检查Glide是否初始化
//得到一个glide对象 通过glide得到一个RequestManager 在glide构造方法中
return Glide.get(context).getRequestManagerRetriever();
}
RequestManagerRetriever
得到一个requestManagerRetriever
对象,并且这里还需要返回一个Glide
实例
public class Glide implements ComponentCallbacks2 {
private static volatile Glide glide;
private static volatile boolean isInitializing; //是否初始化
//单例得到Glide
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
//如果已经初始化 抛出异常
}
isInitializing = true;
initializeGlide(context); //初始化Glide
isInitializing = false;
}
private static void initializeGlide(@NonNull Context context) {
//GlideBuilder来初始化Glide
initializeGlide(context, new GlideBuilder());
}
//初始化Glide
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext(); //得到当前的Application
//获取 @GlideModule 注解驱动生成的 GeneratedAppGlideModuleImpl和GeneratedAppGlideModuleFactory 类
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
//返回一个空的collections的集合
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
//判断@GlideModule的类是否为空或者是在Manifest中去注解isManifestParsingEnabled默认情况下返回True
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
//通过Manifest中去得到GlideModule模块
manifestModules = new ManifestParser(applicationContext).parse();
}
//当返回的GlideModule注解不为空并且注解生成的类模块不为空
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
//得到当前的GlideModule注解模块
Set<Class<?>> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
//通过iterator来循环
Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
//得到当前的注解模块
com.bumptech.glide.module.GlideModule current = iterator.next();
//如果已经排除的模块不包含当前的类,结束本次循环
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
//如果包含当前类 则移除这个类
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
//尝试从注解生成的 annotationGeneratedModule 中获取 RequestManager 的构造工厂对象
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
//设置当前的请求管理工厂
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//构建Glide实体对象
Glide glide = builder.build(applicationContext);
//循环mainFast注解注册的模块 Glide3 版本通用的注册模式 V4版本不再使用
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
//尝试去注册Glide ||得到注册的生命周期, Glide对象 ,注册管理器,包含注册编码,解码和编码的逻辑
module.registerComponents(applicationContext, glide, glide.registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: " + module.getClass().getName(), e);
}
}
//如果当前annotationGeneratedModule 注解的模块不为空
if (annotationGeneratedModule != null) {
//注册Glide组件
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
//把Glide绑定到glide传进来的生命周期中 用于检测系统 Config 改变和内存占用量低的信号
applicationContext.registerComponentCallbacks(glide);
//存在静态的成员变量中
Glide.glide = glide;
}
}
Glide的构建过程
public final class GlideBuilder {
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
//管理线程池的引擎
private Engine engine;
//享元复用池
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
//线程池
private GlideExecutor sourceExecutor;
private GlideExecutor diskCacheExecutor;
private GlideExecutor animationExecutor;
//磁盘缓存
private DiskCache.Factory diskCacheFactory;
//内存缓存
private MemorySizeCalculator memorySizeCalculator;
private MemoryCache memoryCache;
//连接监视器
private ConnectivityMonitorFactory connectivityMonitorFactory;
//请求构造器
private RequestOptions defaultRequestOptions = new RequestOptions();
//请求构建工厂
@Nullable
private RequestManagerFactory requestManagerFactory;
//是否保留Activity中的资源
private boolean isActiveResourceRetentionAllowed;
//请求监听器
@Nullable
private List<RequestListener<Object>> defaultRequestListeners;
@NonNull
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();
}
//bitMap的复用池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
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);
}
//一个 RequestManagerRetriever 对象
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
//构建一个Glide对象
return new Glide(
context, //上下文环境
engine,//执行引擎
memoryCache,//内存缓存
bitmapPool,//bitMap的复用池
arrayPool,//数组复用池
requestManagerRetriever,//请求管理类
connectivityMonitorFactory,//连接监听器
logLevel,//log等级
defaultRequestOptions.lock(),//默认请求选项
defaultTransitionOptions,//默认的转换选项
defaultRequestListeners,//默认的请求监听
isLoggingRequestOriginsEnabled);//是否开启请求资源的日志
}
}
Glide 对象的构建过程异常的复杂, 笔者调整了部分的数据, 它们的流程如下
- 构建线程池 ------>根据不同的任务构建不同的线程池
- 构建内存缓存策略 ----> 1.内存计算器 2. Lru缓存算法
- 构建对象复用池
- 构建工厂类 -->创了一个
RequestManagerRetriever
对象的工厂 - 构建 Glide 执行引擎 ----->用于管理线程池和缓存
- 创建 Glide 对象
- 将
Glide Builder
中的数据导入 - 构建一个
registry
, 注册了众多的编解码器 - 构建了一个
Glide Context
对象, 描述其数据资源的上下文
- 将
从 Glide 构造的流程中, 可以看到它主要有五个核心部分, 线程池, 内存缓存策略, 对象复用策略和图片 ,音视频的编解码
在创建GlideBuilder.build
中, 我们看到了它 new 了一个RequestManagerRetriever
对象并且传递到了 Glide 对象内部, 于是通过 Glide.getRequestManagerRetriever
就可以很方便的获取到 RequestManagerRetriever
这个对象了
获取到了 RequestManagerRetriever
实例后, 接下来就可以通过 RequestManagerRetriever.get()
方法获取 RequestManager
对象了
得到RequestManager
public class RequestManagerRetriever implements Handler.Callback {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
//下面是判断当前的Context的载体
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
//若不在 MainThread 或 context 为 Application 的类型, 则使用 ApplicationManager
return getApplicationManager(context);
}
-
RequestManagerRetriever.get
方法会判断 Context 的类型- 若在主线程并且不为
Application
类型的 Context 则找寻其依赖的 Activity - 若非主线程或为
Application
类型的 Context, 则使用ApplicationManage
- 若在主线程并且不为
获取Activity
的RequestManager
public RequestManager get(@NonNull Activity activity) {
//判断是否在子线程
if (Util.isOnBackgroundThread()) {
//子线程返回Application对象的RequestManager
return get(activity.getApplicationContext());
} else {
//主线程
assertNotDestroyed(activity); //不能在销毁Activity时候去加载
android.app.FragmentManager fm = activity.getFragmentManager();//获取其 FragmentManager
return fragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//1. 从 Activity 中获取一个 RequestManagerFragment, 用于监管 Activity 的声明周期
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
// 2. 获取 Fragment 中保存的当前页面的请求管理器
RequestManager requestManager = current.getRequestManager();
// 3. 不存在则创建一个请求管理器保存在 RequestManagerFragment 中
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
//返回这个请求管理器
return requestManager;
}
// 描述一个即将被 FragmentManager 添加的 RequestManagerFragment 缓存
final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
new HashMap<>();
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//1 尝试从 FragmentManager 中获取这个 Fragment
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//2 不存在则添加一个
if (current == null) {
//3 从 pendingRequestManagerFragments 缓存中获取一个
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
//3.1 创建并更新到缓存
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
//执行Glide生命周期的start
current.getGlideLifecycle().onStart();
}
//3.2 添加到等待被添加的缓存中因为添加到 FragmentManager 有延迟, 用这种方式防止同一时间创建了两个 RequestManagerFragment 对象添加到 Activity 中
pendingRequestManagerFragments.put(fm, current);
//3.3 添加到 FragmentManager 中
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//3.4 添加到 FragmentManager 成功, 通过 Handler 移除这个缓存
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
可以看到 RequestManagerRetriever
的 get
方法主要是在 Activity
页面中添加一个RequestManagerFragment
实例, 以便用于监听Activity
的生命周期, 然后给这个 Fragment 注入一个RequestManager
, 其处理的细节代码中也注释的比较详细
- 其中有个非常引人注目的细节, 考虑到将
FragmentManger
添加Fragment
有延迟, 为了防止同一时间创建了两个RequestManagerFragment
添加到FragmentManager
, 因此它使用了pendingRequestManagerFragments
进行缓存
获取 Application
的RequestManager
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
//构建Glide对象
Glide glide = Glide.get(context.getApplicationContext());
//得到RequestManager对象
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
关于with方法总结
至此 with方法全部结束简单总结一下
- 构建
Glide
实例 - 获取
RequestManagerRetriever
对象 - 构建
RequestManager
对象- 若可以绑定
Activity
, 则为Activity
添加一个RequestManagerFragment
, 其内部含有ReqeustManager
对象, 以便后续直接根据Activity
的生命周期管控Glide
请求的处理 - 若非可绑定
Activity
, 则获取一个单例的applicationManager
专门用于处理这类请求
- 若可以绑定
Load方法(RequestManager)
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
//load
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
// 构建一个 RequestBuilder,描述一个目标资源为 Drawable 的图片加载请求
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);
}
}
- load方法()
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
private Object model;//描述已经加载的资源
// 描述这个请求是否已经添加了加载的数据源
private boolean isModelSet;
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
}
Into方法(RequestBuilder)
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread(); //检测是否是主线程
Preconditions.checkNotNull(view); //检测View是否为空
//根据 view 的 scaleType 重构 RequestOptions RequestBuilder 直接继承了 BaseRequestOptions
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
// 1.1 克隆原 RequestOptions, 配置一个 CenterCrop 的缩放选项
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.
}
}
// 2. 调用 into 方法, 创建并且执行请求
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
可以看到 into 方法中
- 第一步是根据
ImageView
的ScaleType
来配置Options
选项 - 第二步调用了重载方法
into
执行后续构建请求操作
配置 Options
public abstract class BaseRequestOptions<T extends BaseRequestOptions<T>> implements Cloneable {
...
public T optionalCenterCrop() {
//optionalTransform DownsampleStrategy 描述降采样压缩的策略 CenterCrop 描述图像变化方式
return optionalTransform(DownsampleStrategy.CENTER_OUTSIDE, new CenterCrop());
}
final T optionalTransform(@NonNull DownsampleStrategy downsampleStrategy,
@NonNull Transformation<Bitmap> transformation) {
if (isAutoCloneEnabled) {
return clone().optionalTransform(downsampleStrategy, transformation);
}
//2. 将降采样压缩策略添加到 options 中
downsample(downsampleStrategy);
// 3. 将图像变化方式添加到 transformations 中
return transform(transformation, /*isRequired=*/ false);
}
//压缩策略
public T downsample(@NonNull DownsampleStrategy strategy) {
//调用了 set, 将降采样策略保存到 options 中
return set(DownsampleStrategy.OPTION, Preconditions.checkNotNull(strategy));
}
public <Y> T set(@NonNull Option<Y> option, @NonNull Y value) {
if (isAutoCloneEnabled) {
return clone().set(option, value);
}
Preconditions.checkNotNull(option);
Preconditions.checkNotNull(value);
// 2.2 添加到 options 缓存中
options.set(option, value);
return selfOrThrowIfLocked();
}
T transform(
@NonNull Transformation<Bitmap> transformation, boolean isRequired) {
if (isAutoCloneEnabled) {
return clone().transform(transformation, isRequired);
}
// 3.1 调用了 transform 的重载方法, 将这个图像变化的方式作用到多种资源类型上
DrawableTransformation drawableTransformation =
new DrawableTransformation(transformation, isRequired);
transform(Bitmap.class, transformation, isRequired);//Bitmap类型资源
transform(Drawable.class, drawableTransformation, isRequired);//Drawable类型资源
transform(BitmapDrawable.class, drawableTransformation.asBitmapDrawable(), isRequired);//BitmapDrawable类型资源
transform(GifDrawable.class, new GifDrawableTransformation(transformation), isRequired);//动图资源
return selfOrThrowIfLocked();
}
private Map<Class<?>, Transformation<?>> transformations = new CachedHashCodeArrayMap<>();
<Y> T transform(@NonNull Class<Y> resourceClass, @NonNull Transformation<Y> transformation,
boolean isRequired) {
if (isAutoCloneEnabled) {
return clone().transform(resourceClass, transformation, isRequired);
}
Preconditions.checkNotNull(resourceClass);//空检测
Preconditions.checkNotNull(transformation);//空检测
// 3.2 添加到了 transformations 缓存中
transformations.put(resourceClass, transformation);
fields |= TRANSFORMATION;
isTransformationAllowed = true;
fields |= TRANSFORMATION_ALLOWED;
isScaleOnlyOrNoTransform = false;
if (isRequired) {
fields |= TRANSFORMATION_REQUIRED;
isTransformationRequired = true;
}
return selfOrThrowIfLocked();
}
}
可以看到配置缩放选项的操作除了添加了图像变化操作, 还设定了采样方式, 分别保存在 transformations 和 options 中
构建 Request
请求
return into(glideContext.buildImageViewTarget(view, transcodeClass),
// 2.1 调用 GlideContext.buildImageViewTarget 构建一个 ViewTarget
requestOptions,
Executors.mainThreadExecutor());
我们知道 GlideContext
是在 Glide
对象构造时一并创建的, 它是 Context
的装饰者对象, 在 Application
类型的 Context
中, 添加了 Glide
相关的数据, 我们先看看它是如何构建 ViewTarget
public class GlideContext extends ContextWrapper {
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
// 调用工厂类来创建一个 imageView 的 ViewTarget
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
}
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
// 根据目标编码的类型来创建不同的 ViewTarget 对象, 因为我们没有 asBitmap, 因此这里为 Drawable
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)");
}
}
}
可以看到 GlideContext
中通过工厂类创建了ImageView
的 ViewTarget
的, 它描述的是图像处理结束之后, 最终要作用到的 View 目标
构建好了ViewTarge
, 接下来就可以分析重载的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()");
}
// 调用 buildRequest 构建了一个 request 请求
Request request = buildRequest(target, targetListener, options, callbackExecutor);
// 处理这个 ViewTarget 之前的请求与新请求的冲突
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
// 调用了请求 RequestManager.track 方法执行请求
requestManager.track(target, request);
return target;
}
可以看到调用了buildRequest
构建了一个 Glide
的请求, 其构建过程也非常有意思, 最终最调用SingleRequest.obtain
构建一个Request
的实例对象, 之后便是调用 RequestManager.track
将其分发并执行了
Into的总结
- 根据
ImageView
构建采样压缩和图像变化的策略保存在Options
和Transform
中 - 构建
ViewTarget
描述这个请求要作用的View
对象 - 构建
Request
请求并执行
获取数据源
在上面的into
方法中我们已经成功构建一个Request 这里我们继续往下看
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);//跟踪生命周期
requestTracker.runRequest(request);//开始请求数据
}
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
//开始执行请求
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
public final class SingleRequest<R> implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
public synchronized void begin() {
....
//完成状态
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
//等待状态
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//表示尺寸准备好了
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
....
}
public synchronized void onSizeReady(int width, int height) {
...
//通过引擎的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);
....
}
}
任务的构建(load)
public synchronized <R> LoadStatus load( ...) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
//根据传入的参数, 构建这个请求的 key
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
// 2. 尝试从 ActiveResources 缓存中查找这个 key 的缓存
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
// 若缓存存在, 则直接回调 onResourceReady 处理后续操作
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//尝试从 LruResourceCache 中找寻这个资源
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
// 回调 onResourceReady 处理后续操作
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//从缓存中查找 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);
}
//返回加载状态即可
return new LoadStatus(cb, current);
}
//构建一个新的引擎任务
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//构建解码任务
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//添加到任务缓存
jobs.put(key, engineJob);
//添加回调监听器
engineJob.addCallback(cb, callbackExecutor);
//执行任务
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
Load方法的作用是:
构建这个请求的
key
从缓存中查找
key
对应的资源, 若存在直接回onResourceReady
表示资源准备好了从缓存中查找
key
对应的任务若存在则说明无需再次获取资源
-
不存在需要构建新的任务
- 构建引擎任务
EngineJob
- 引擎的任务为解码任务
DecodeJob
- 将任务添加到缓存, 防止多次构建
- 执行任务
- 构建引擎任务
任务执行(start)
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor(); //获取线程池
executor.execute(decodeJob); //执行线程池
}
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
public void run() {
GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
//调用runWrapped
runWrapped();
} catch (CallbackException e) {
...
}
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
//获取任务的场景
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 Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
//若我们配置的缓存策略允许从 资源缓存 中读数据, 则返回 Stage.RESOURCE_CACHE
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
//若我们配置的缓存策略允许从 源数据缓存中读数据, 则返回 Stage.DATA_CACHE
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// 若只能允许从缓存中获取数据, 则直接 FINISH, 否则返回 Stage.SOURCE, 意为加载一个新的资源
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
//获取这个场景的执行者
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
//资源磁盘缓存的执行者
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
//源数据磁盘缓存的执行者
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
//无缓存, 获取数据的源的执行者
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;
//currentGenerator.startNext()执行请求操作
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);//得到下一个任务
currentGenerator = getNextGenerator();//得到下一个任务的执行者
if (stage == Stage.SOURCE) {
//重新调度任务
reschedule();
return;
}
}
}
}
DecodeJob
任务执行时, 它根据不同的场景, 获取不同的场景执行器, 然后调用了它们的 startNext
方法加载请求任务的数据, 其映射表为
场景 | 场景描述 | 场景执行器 |
---|---|---|
Stage.RESOURCE_CACHE | 从磁盘中缓存的资源中获取数据 | ResourceCacheGenerator |
Stage.DATA_CACHE | 从磁盘中缓存的源数据中获取数据 | DataCacheGenerator |
Stage.SOURCE | 重新请求数据 | SourceGenerator |
我们知道在 Engine
中, 尝试从内存缓存中获取资源, 而 DecodeJob
则是尝试从磁盘缓存中获取资源, 我们这里主要查看 SourceGenerator.startNext
是如何加载请求任务的数据的
获取源数据(startNext)
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
// 1. 从 DecodeHelper 的数据加载集合中, 获取一个数据加载器
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
//2. 使用加载器中 fetcher 执行数据加载
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
SourceGenerator
主要有两步
- 调用
DecodeHelper.getLoadData
获取当前请求的数据加载器 - 调用加载器中的
fetcher.loadData
真正的执行数据加载
获取数据加载器
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
// 1. 从 Glide 注册的 register 中获取请求 model 加载器
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
// 遍历每一个 modelLoaders
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
// 2. 通过 modelLoaders 构建 loadData
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
// 添加到缓存
loadData.add(current);
}
}
}
return loadData;
}
- 它会找到一个
ModelLoader
的实现类, 通过这个实现类的handles
方法, 判断是否可以加载这个model
- 这里我们的
model
以网络的 URL 资源举例, 它的实现类为HttpGlideUrlLoader
我们看看它如何构建一个LoadData
对象的
- HttpGlideUrlLoader.java
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
@NonNull Options options) {.
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);
// 创建了一个 LoadData 对象, 并且实例化了一个 HttpUrlFetcher 给它
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
好的, 可以看到对于 URL 的加载, 其 fetcher
为一个 HttpUrlFetcher
的实例, 接下来我们看看数据加载的流程
执行数据加载
- HttpUrlFetcher.java
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
// 获取网络图片, 内部使用了 HttpConnection 实现, 仅仅做了重定向的处理
//loadDataWithRedirects 内部采用HttpConnection 实现
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
// 将 inputStream 回调出去
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}
数据加载的过程也是很简单的, HttpUrlFetcher
它使用了 HttpConnection
发起了网络请求, 获取了数据流, 至此数据资源的获取就已经完成了, 后面要做的便是最重要的数据处理了, 它通过回调的方式将 InputStream
扔了出去, 最终会回溯到 DecodeJob
的 onDataFetcherReady
这个方法中
总结
走到这里, 一个请求的数据源获取就已经完成, 还剩下对数据源的处理操作, 一次 Glide 数据加载就完成了, 我们先回顾一下这次加载的流程图
优先从 memoryCache
中获取 (内存)
ActiveResource
LruResourceCache
次优先从diskCache
中获取 (磁盘)
-
Resource
资源缓存 -
Data
源数据缓存
执行新的加载任务获取源数据 (网络请求)
- 通过
SourceGenerator
获取数据 - 通过
HttpUrlFetcher
获取网络数据流
数据源的处理
DecodeJob.java
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey;//保存数据的 key
this.currentData = data;//保存数据的实体
this.currentFetcher = fetcher;//保存数据的获取器
this.currentDataSource = dataSource;//数据来源: url 为 REMOTE 类型的枚举, 表示从远程获取
this.currentAttemptingKey = attemptedKey;//尝试解码的key
if (Thread.currentThread() != currentThread) { //不是主线程
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);//线程调度
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");//开启跟踪
try {
//尝试解析数据
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();//结束
}
}
}
private void decodeFromRetrievedData() {
...
Resource<R> resource = null;
try {
//解析数据
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
//解析成功,通知外界资源解析成功
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
资源的获取
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();
}
}
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
// 获取当前数据类的解析器 LoadPath
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
// 通过解析器来解析来解析数据
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);
//根据数据类型获取一个数据重造器, 获取的数据为 InputStream, 因此它是一个 InputStreamRewinder 的实例
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// 将解析资源的任务转移到了 LoadPath.load 方法中
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
可以看到为了解析数据, 首先构建了一个 LoadPath, 然后创建了一个 InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作到了 LoadPath.load 方法中
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;
//遍历内部存储的 DecodePath 集合, 通过他们来解析数据
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
//调用 DecodePath.decode 真正进行数据的解析
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;
}
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
//1. 调用 decodeResource 将源数据解析成中间资源
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
//2. 调用 DecodeCallback.onResourceDecoded 处理中间资源
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
//3. 调用 ResourceTranscoder.transcode 将中间资源转为目标资源
return transcoder.transcode(transformed, options);
}
private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options) throws GlideException {
List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
try {
//调用了 decodeResourceWithList
return decodeResourceWithList(rewinder, width, height, options, exceptions);
} finally {
listPool.release(exceptions);
}
}
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
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();
// 调用 ResourceDecoder.decode 解析源数据
result = decoder.decode(data, width, height, options);
}
} 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;
}
可以看到数据解析的任务最重是通过 DecodePath
来执行的, 它内部有三个操作
- 调用
decodeResource
将源数据解析成资源- 源数据:
InputStream
- 中间产物:
Bitmap
- 源数据:
- 调用
DecodeCallback.onResourceDecoded
处理资源 - 调用
ResourceTranscoder.transcode
将资源转为目标资源- 目标资源类型:
Drawable
- 目标资源类型:
1. 解析源数据
StreamBitmapDecoder.java
public Resource<Bitmap> decode(@NonNull InputStream source, int width, int height,
@NonNull Options options)
throws IOException {
final RecyclableBufferedInputStream bufferedStream;
final boolean ownsBufferedStream;
...
ExceptionCatchingInputStream exceptionStream =
ExceptionCatchingInputStream.obtain(bufferedStream);
MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream);
UntrustedCallbacks callbacks = new UntrustedCallbacks(bufferedStream, exceptionStream);
try {
// 根据请求配置的数据, 对数据流进行采样压缩, 获取到一个 Resource<Bitmap>
return downsampler.decode(invalidatingStream, width, height, options, callbacks);
} finally {
exceptionStream.release();
if (ownsBufferedStream) {
bufferedStream.release();
}
}
}
Downsampler.java
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
Options options, DecodeCallbacks callbacks) throws IOException {
Preconditions.checkArgument(is.markSupported(), "You must provide an InputStream that supports"
+ " mark()");
byte[] bytesForOptions = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
BitmapFactory.Options bitmapFactoryOptions = getDefaultOptions();
bitmapFactoryOptions.inTempStorage = bytesForOptions;
DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
DownsampleStrategy downsampleStrategy = options.get(DownsampleStrategy.OPTION);
boolean fixBitmapToRequestedDimensions = options.get(FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS);
boolean isHardwareConfigAllowed =
options.get(ALLOW_HARDWARE_CONFIG) != null && options.get(ALLOW_HARDWARE_CONFIG);
try {
Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
requestedHeight, fixBitmapToRequestedDimensions, callbacks);
//用线程池把流转为Resource<Bitmap>
return BitmapResource.obtain(result, bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
byteArrayPool.put(bytesForOptions);
}
}
可以看到它内部通过Downsampler.decode
方法对数据流进行采样压缩, 来获取这个流的Bitmap
- 这个采样的策略就是我们在构建
Request
时传入的, 其采样压缩的细节, 并不是我们本次关注的重点
我们看看获取到了 Resource
之后, 如何处理这个资源
2. 资源的处理
可以看到, 当我们将源数据解析成对应的资源之后, 便会调用 DecodeCallback.onResourceDecoded
处理资源, 我们看看它
的处理过程
@Override
public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
return DecodeJob.this.onResourceDecoded(dataSource, decoded);
}
<Z> Resource<Z> onResourceDecoded(DataSource dataSource,
@NonNull Resource<Z> decoded) {
@SuppressWarnings("unchecked")
//1. 获取数据资源的类型
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
//2. 若非从资源磁盘缓存中获取的数据源, 则对资源进行 transformation 操作
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
if (!decoded.equals(transformed)) {
decoded.recycle();
}
// 3. 构建数据编码的策略
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;
}
//4. 根据编码策略, 构建缓存的 key
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
key = new DataCacheKey(currentSourceKey, signature);
break;
case TRANSFORMED: // 资源数据的 key
key =
new ResourceCacheKey(
decodeHelper.getArrayPool(),
currentSourceKey,
signature,
width,
height,
appliedTransformation,
resourceSubClass,
options);
break;
default:
throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
}
// 5. 初始化编码管理者, 用于提交内存缓存
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
}
// 返回 transform 之后的 bitmap
return result;
}
可以看到 onResourceDecoded
中, 主要是对中间资源做了如下的操作
- 对资源进行
transformed
操作- 将资源转为目标效果, 如在构建
request
时, 设置的CenterCrop
- 将资源转为目标效果, 如在构建
- 构建磁盘缓存的
key
3. 将数据转为目标格式
目标数据为 Drawable, 因此它的转换器为 BitmapDrawableTranscoder
BitmapDrawableTranscoder .java
@Override
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
@NonNull Options options) {
//调用了 LazyBitmapDrawableResource.obtain 获取 Resource<BitmapDrawable> 的实例对象
return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}
LazyBitmapDrawableResource.java
public static Resource<BitmapDrawable> obtain(
@NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
if (bitmapResource == null) {
return null;
}
//创建了一个 LazyBitmapDrawableResource
return new LazyBitmapDrawableResource(resources, bitmapResource);
}
private LazyBitmapDrawableResource(@NonNull Resources resources,
@NonNull Resource<Bitmap> bitmapResource) {
this.resources = Preconditions.checkNotNull(resources);
this.bitmapResource = Preconditions.checkNotNull(bitmapResource);
}
@Override
public BitmapDrawable get() {
// Get 方法反回了一个 BitmapDrawable 对象
return new BitmapDrawable(resources, bitmapResource.get());
}
好的, 转化成目标数据也非常的简单, 它将我们解析到的bitmap
存放到 LazyBitmapDrawableResource
内部, 然后外界通过 get
方法就可以获取到一个 BitmapDrawable
的对象了
4. 解码转换结构图
数据的展示
DecodeJob.java
private void decodeFromRetrievedData() {
...
Resource<R> resource = null;
try {
// 解析 inputStream 获取资源
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
//通知外界资源获取成功
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
// 回调上层资源
notifyComplete(result, dataSource);
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
// throws.
onEncodeComplete();
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
//从 DecodeJob 的构建中, 我们知道这个 Callback 是一 EngineJob
callback.onResourceReady(resource, dataSource);
}
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
DecodeJob.decodeFromRetrievedData
中, 主要做了两个操作
- 回调
EngineJob.onResourceReady
资源准备好了 - 将数据缓存到磁盘
EngineJob.java
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
...
// 1. 通知上层 Engine 任务完成了
engineJobListener.onEngineJobComplete(this, localKey, localResource);
//回调给 ImageViewTarget 展示资源
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
-
EngineJob
中也是有两步操作, 一个是通知上层任务完成了, 另一个是回调给ImageViewTarget
展示资源
Engine .java
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);
}
我们知道在请求发起前是Engine
尝试通过内存缓存读, 结束之后再回到 Engine
添加内存缓存也不足为奇了
ImageViewTarget.java
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);// 处理一些 transition 变化,
} 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);
}
DrawableImageViewTarget .java
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
ImageViewTarget
调用了子类重写的 setResource
方法, 将数据填充进去, 至此一次Glide
图像加载就完成了
流程回顾
通过一次流程分析我们得知, 整个Glide
图片加载主要有如下几步
- 请求管理器的构建
- 一个
Context
对应一个RequestManager
- 一个
- 请求的构建
- 请求的宽高、采样的方式、
transform
变化...
- 请求的宽高、采样的方式、
- 通过请求获取资源
-
Engine
从内存缓存中查找- 从
ActiveResources
缓存中查找 - 从
LruResourceCache
缓存中查找
- 从
- 内存缓存不存在, 则构建任务执行
- 构建一个
EngineJob
描述一个请求任务, 任务类型为DecodeJob
-
DecodeJob
从diskCache
中查找 -
diskCache
不存在, 则通过网络请求, 获取数据源 - 通过
Downsampler
解析源数据并进行采样压缩获取Bitmap
- 对
Bitmap
进行transform
处理- 构建磁盘缓存的
key
- 构建磁盘缓存的
- 将
transform
之后的Bitmap
转为Resource
回传给上层-
DecodeJob
进行磁盘缓存
-
-
- 构建一个
-
Engine
对资源进行内存缓存
-
- 传递给
View
进行展示
看了 Glide 的加载流程, 我似乎能够明白为什么他是 Google 推荐的图片加载框架了, 内部细节的处理做的非常的到位, 而且使用GlideContext
用于描述Glide
的上下文, 与 Android 的 Context
巧妙的融合在一起, 读起来真有一种阅读 Android 源码的既视感
不过这只是最简单的流程, 而且 Glide 支持 Gif, 视频加载操作, 可想而知其内部的 Decorder
处理了多少逻辑代码, 如此复杂的流程, 嵌套了如此之多的回调, 无疑增加了我们阅读源码的难度, 若是将这些操作分层, 并且使用拦截器去实现, 我想定会让一次图像加载操作变得更加清晰明了