本文介绍 Glide 图片加载框架,包含简单的使用和源码解析。
Glide 是一个快速高效的 Android 图片加载库,注重于平滑的滚动。Glide 提供了易用的 API,高性能、可扩展的图片解码管道,以及自动的资源池技术。https://muyangmin.github.io/glide-docs-cn/
Glide 支持拉取,解码和展示视频快照,图片,和 GIF 动画。Glide 的 API 是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide 使用的是一个定制化的基于 HttpUrlConnection 的栈,但同时也提供了与 Google Volley 和 Square OkHttp 快速集成的工具库。
一、使用方法
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
Glide.with(this)
.asBitmap()
.load("https://cdn.wshunli.com/logo.png")
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)
.into(imageView);
https://www.wshunli.com/posts/d82d8606.html
https://muyangmin.github.io/glide-docs-cn/doc/getting-started.html
二、Glide 图片加载流程
2.1、with() 方法
// Glide
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@Deprecated
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
//
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// ***
// (1)构造 Glide 对象,单例模式
return Glide.get(context).getRequestManagerRetriever();
}
// (1)构造
private static volatile Glide glide;
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
// 最终 GlideBuilder 构造 glide 对象
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Glide glide = builder.build(applicationContext);
Glide.glide = glide;
}
// (2)获取 RequestManagerRetriever
private final RequestManagerRetriever requestManagerRetriever;
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
然后调用 RequestManagerRetriever#get()
获取 RequestManager
2.2、load() 方法
// RequestManager
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
if (isAutoCloneEnabled()) {
return clone().loadGeneric(model);
}
this.model = model;
isModelSet = true;
return selfOrThrowIfLocked();
}
将数据存入 RequestManager ,最后返回 RequestBuilder对象
2.3、into() 方法
// RequestBuilder
private final GlideContext glideContext;
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
//***
// (2) into 方法
return into(
// (1) 构造 ViewTarget
glideContext.buildImageViewTarget(view, transcodeClass),
// requestOptions
requestOptions,
// 运行在主线程的线程池
Executors.mainThreadExecutor());
}
(1) ImageViewTargetFactory 构造 ViewTarget
// GlideContext
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
// ImageViewTargetFactory
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(
@NonNull ImageView view, @NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
}
(2)RequestBuilder#into 方法
// RequestBuilder
private final RequestManager requestManager;
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()");
}
// 构造 SingleRequest 请求对象
Request request = buildRequest(target, targetListener, options, callbackExecutor);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
// 发送请求
requestManager.track(target, request);
return target;
}
// RequestManager
private final RequestTracker requestTracker;
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
// RequestTracker 真正执行请求
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
// (3)发送请求
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
(3)SingleRequest 发送请求
public void begin() {
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
// 记载失败回调
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
// ***
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 准备好加载图片
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
}
private volatile Engine engine;
public void onSizeReady(int width, int height) {
// ***
//(4)Engine 的 load() 方法
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
// SingleRequest 对象
this,
callbackExecutor);
// ***
}
(4)Engine#load 方法
// Engine#load 最终执行 waitForExistingOrStartNewJob 方法
private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
// SingleRequest 对象
ResourceCallback cb,
Executor callbackExecutor,
EngineKey key,
long startTime) {
// ***
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
// ***
jobs.put(key, engineJob);
// (5) 最终回调 SingleRequest#onResourceReady
engineJob.addCallback(cb, callbackExecutor);
// ***
return new LoadStatus(cb, engineJob);
}
(5) SingleRequest#onResourceReady
// SingleRequest
public void onResourceReady(
Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
stateVerifier.throwIfRecycled();
Resource<?> toRelease = null;
try {
synchronized (requestLock) {
// ***
// 获取 GlideBitmapDrawable、GifDrawable 对象
Object received = resource.get();
// ***
onResourceReady(
(Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
}
} finally {
if (toRelease != null) {
engine.release(toRelease);
}
}
}
private final Target<R> target;
private void onResourceReady(
Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
// ***
isCallingCallbacks = true;
try {
// ***
// 在 (2)构造 SingleRequest 请求对象时,传入 (1)构造的 ViewTarget
// BitmapImageViewTarget、DrawableImageViewTarget 类型
// 最终回调父类 ImageViewTarget#onResourceReady
target.onResourceReady(result, animation);
// ***
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
(6)ImageViewTarget#onResourceReady 方法
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
setResource(resource);
maybeUpdateAnimatable(resource);
}
// 抽象方法,最终调用子类 setResource 方法
protected abstract void setResource(@Nullable Z resource);
// DrawableImageViewTarget#setResource
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
// BitmapImageViewTarget#setResource
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
好复杂啊。
三、缓存机制
Glide.with(this)
.load("https://cdn.wshunli.com/logo.png")
// 内存缓存
.skipMemoryCache(true)
// 硬盘缓存
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
3.1、缓存 Key
// Engine#load()
private final EngineKeyFactory keyFactory;
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
// 获取缓存 key
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
EngineResource<?> memoryResource;
synchronized (this) {
// 3.2内存缓存
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// ***
// waitForExistingOrStartNewJob
}
}
// 加载图片
cb.onResourceReady(
memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return null;
}
3.2、内存缓存
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
// skipMemoryCache 方法设置
if (!isMemoryCacheable) {
return null;
}
// (1)从 activeResources 中获取资源,正在使用中
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
return active;
}
// (2)LruCache 算法获取
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
return cached;
}
return null;
}
// (1)
private final ActiveResources activeResources;
private EngineResource<?> loadFromActiveResources(Key key) {
EngineResource<?> active = activeResources.get(key);
if (active != null) {
active.acquire();
}
return active;
}
// (2)
private EngineResource<?> loadFromCache(Key key) {
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
cached.acquire();
activeResources.activate(key, cached);
}
return cached;
}
private EngineResource<?> getEngineResourceFromCache(Key key) {
Resource<?> cached = cache.remove(key);
final EngineResource<?> result;
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
result = (EngineResource<?>) cached;
} else {
result =
new EngineResource<>(
cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
}
return result;
}
3.3、硬盘缓存
Glide 的硬盘缓存策略:
DiskCacheStrategy.NONE: 表示不缓存任何内容
DiskCacheStrategy.DATA: 表示只缓存原始图片
DiskCacheStrategy.RESOURCE: 表示只缓存转换过后的图片
DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片
DiskCacheStrategy.AUTOMATIC: 表示让 Glide 根据图片资源智能地选择使用哪一种缓存策略
1、Engine#load 方法中,没有内存缓存会调用 waitForExistingOrStartNewJob 方法
// Engine
private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor,
EngineKey key,
long startTime) {
// ***
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);
}
// EngineJob#start
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
// 在线程池中执行 decodeJob
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
executor.execute(decodeJob);
}
2、DecodeJob#run 方法
// DecodeJob
public void run() {
// ***
runWrapped();
// ***
}
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);
}
}
参考资料
1、Glide源码分析 | lightSky'Blog
http://www.lightskystreet.com/2015/10/12/glide_source_analysis/
2、Android Glide源码解析 - 简书
https://www.jianshu.com/p/0c383eaa5675
3、Android Glide源码解析 | Frodo's Blog
http://frodoking.github.io/2015/10/10/android-glide/
4、Android源码分析:手把手带你分析 Glide的缓存功能 - CSDN博客
https://blog.csdn.net/carson_ho/article/details/79256892
评论 (0)