接续,开始解析数据
onDataFetcherReady方法中主要工作
- 解析获取的数据
- 返回图片资源
下面接着看
DecodeJob#decodeFromData
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
@SuppressWarnings("unchecked")
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
==================================================
= 获取当前数据类的解析器LoadPath,此时的data为InputStream对象
===================================================
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);
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
listPool.release(throwables);
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
============================================
= 调用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 {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
// 该transcoder为BitmapDrawableTranscoder
return transcoder.transcode(transformed, options);
}
- LoadPath的load方法最终会调用DecodePath的decode来解析数据,DecodePath的decode的主要工作就是获取到Resource对象,然后还要将Resource对象转化成LazyBitmapDrawableResource。考虑到篇幅问题,在这里就不分析如何得到Resource对象,只分析如何将数据转化为目标格式,可以通过Glide构造中的注册表中找出Bitmap转化成Drawable的转化器为BitmapDrawableTranscoder,所以实际上调用了BitmapDrawableTranscoder的transcode来进行转换。
BitmapDrawableTranscoder#transcode
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
@NonNull Options options) {
//获取LazyBitmapDrawableResource对象
return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}
LazyBitmapDrawableResource#obtain
public static Resource<BitmapDrawable> obtain(
@NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
if (bitmapResource == null) {
return null;
}
//创建了一个LazyBitmapDrawableResource对象
return new LazyBitmapDrawableResource(resources, bitmapResource);
}
public BitmapDrawable get() {
//返回一个BitmapDrawable对象
return new BitmapDrawable(resources, bitmapResource.get());
}
- 追踪下去可以发现transcode最终会得到一个封装了Resource的对象,然后看LazyBitmapDrawableResource的get方法,可以得到一个BitmapDrawable对象,即目标格式。到这里就成功将数据解析成LazyBitmapDrawableResource对象。
在主线程中显示图片
DecodeJob#decodeFromRetrievedData
private void decodeFromRetrievedData() {
....
try {
//解析成功后resource为封装了Resource<Bitmap>的LazyBitmapDrawableResource对象
//可通过get方法获取到BitmapDrawable对象
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) {
.....
//重点关注
notifyComplete(result, dataSource);
......
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
====================================================================
= 回调,注意此时的callback为EngineJob(可回头看Engine中DecodeJob的创建)
====================================================================
callback.onResourceReady(resource, dataSource);
}
回调数据
这个callback哪个对象呢?我们得找出赋值的地方
//重点关注倒数第二个参数,callback的类型为CallBack
DecodeJob<R> init(
GlideContext glideContext,
Object model,
EngineKey loadKey,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
boolean onlyRetrieveFromCache,
Options options,
Callback<R> callback,
int order) {
decodeHelper.init(
glideContext,
model,
signature,
width,
height,
diskCacheStrategy,
resourceClass,
transcodeClass,
priority,
options,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
diskCacheProvider);
this.glideContext = glideContext;
this.signature = signature;
this.priority = priority;
this.loadKey = loadKey;
this.width = width;
this.height = height;
this.diskCacheStrategy = diskCacheStrategy;
this.onlyRetrieveFromCache = onlyRetrieveFromCache;
this.options = options;
this.callback = callback;
this.order = order;
this.runReason = RunReason.INITIALIZE;
this.model = model;
return this;
}
- 很容易的我们发现在init方法会为callback赋值,这时候得记住callback参数的具体位置为倒数第二个。这时候你会想:哪里会调用DecodeJob的init方法呢?然后揣摩:既然是赋值估计会在构建DecodeJob时候会调用到。于是问题就转换为:上文是在哪个地方构建了DecodeJob?然后心里默念:DecodeJob是用来执行任务的,所以应该在构建任务的时候会调用!(不过大多数的情形是:脑子里一片空白,压根想不出来,反正笔者在这里就想不出来。所以这时候就可以直接往上找到DecodeJob首次出现的位置),最终是会在Engine的load中找到DecodeJob的构建
Engine#load
public synchronized <R> LoadStatus load(....){
//重点关注倒数最后一个参数
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
}
//重点关注最后一个参数
<R> DecodeJob<R> build(GlideContext glideContext,
Object model,
EngineKey loadKey,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
boolean onlyRetrieveFromCache,
Options options,
DecodeJob.Callback<R> callback) {
DecodeJob<R> result = Preconditions.checkNotNull((DecodeJob<R>) pool.acquire());
return result.init(
glideContext,
model,
loadKey,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
callback,
creationOrder++);
}
}
- 在上面的代码中首先调用了DecodeJobFactory的build方法来构建DecodeJob,DecodeJobFactory是Engine的内部类,然后接着看DecodeJobFactory的build方法,哇!跟我们想的完全一样!build方法中调用了DecodeJob的init方法,找到后可别忘了我们的任务是干嘛的!找到callback的值,于是看回build的callback的参数位置,在最后一个,然后往回看Engine的load中调用build的最后一个参数!engineJob!没错最后找到的callback的类型应该是EngineJob类型的,其实EngineJob是实现了DecodeJob.Callback接口的。所以接下来就会回调EngineJob的onResourceReady方法
EngineJob#onResourceReady
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
//重点关注
notifyCallbacksOfResult();
}
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
......
//重点关注cbs的类型
//查找cbs里面的类型
copy = cbs.copy();
.....
}
//通知上层Engine的任务完成了
listener.onEngineJobComplete(this, localKey, localResource);
for (final ResourceCallbackAndExecutor entry : copy) {
//回调给ImageViewTarget来展示资源
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
回到主线程
- 又到了确定参数类型的时刻了,首先我们先确定EngineJob的onResourceReady方法中最重要的代码片
for (final ResourceCallbackAndExecutor entry : copy) {
//回调给ImageViewTarget来展示资源
entry.executor.execute(new CallResourceReady(entry.cb));
}
在确定分析线程池的execute的方法前,我们需要做的事有:
- 确定entry.executor类型
- 确定entry.cb类型
现在我们知道entry为ResourceCallbackAndExecutor方法,所以我们来看看这个类以及构造器
ResourceCallbackAndExecutor
static final class ResourceCallbackAndExecutor {
final ResourceCallback cb;
final Executor executor;
ResourceCallbackAndExecutor(ResourceCallback cb, Executor executor) {
this.cb = cb;
this.executor = executor;
}
}
可以发现executor和cb都是ResourceCallbackAndExecutor中的成员变量,在构造时被赋值,所以我们需要找到构造ResourceCallbackAndExecutor对象的地方,自然而然我们会锁定上面copy这个变量
EngineJob
final ResourceCallbacksAndExecutors cbs = new ResourceCallbacksAndExecutors();
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
......
//重点关注cbs的类型
//查找cbs里面的类型
copy = cbs.copy();
.....
}
.....
}
ResourceCallbacksAndExecutors copy() {
return new ResourceCallbacksAndExecutors(new ArrayList<>(callbacksAndExecutors));
}
======================================
= cbs赋值的地方
======================================
synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
stateVerifier.throwIfRecycled();
//此时的cb为singleRequest类型,其实现了ResourceCallback接口
//callbackExecutor就是绑定了主线程Handler的线程池
//cbs的类型为ResourceCallbacksAndExecutors
//add的内部实现就是创建ResourceCallbacksAndExecutor并将cb,callbackExecutor赋值到其成员变量
//然后再add到cbs中
cbs.add(cb, callbackExecutor);
......
}
void add(ResourceCallback cb, Executor executor) {
callbacksAndExecutors.add(new ResourceCallbackAndExecutor(cb, executor));
}
- 让我们看看copy赋值调用的地方,就是调用了ResourceCallbacksAndExecutors类型的cbs的copy方法,copy其实就是创建了ResourceCallbacksAndExecutor集合,这个集合其实就是cbs,我们还需要找到cbs赋值的地方,找半天后你会发现在addCallback方法中会找到cbs的add方法,add方法的内部实现其实就是创建ResourceCallbacksAndExecutor并将cb,callbackExecutor赋值到其成员变量中,所以我们还得确定add方法的两个参数是什么?不知道你是否还有印象,当初在构建任务时我们有专门提到过这个addCallback方法,让我们重新看看Engine的load方法。
Engine#load
....
//调用addCallback()注册了一个ResourceCallback
//这里的cb是load方法的倒数第二个参数,load是在singleRequest的onSizeReady()调用的
//查看后cb为singleRequest类型
//重新看回EngineJob的addCallback方法
engineJob.addCallback(cb, callbackExecutor);
//在子线程中执行DecodeJob的run方法
engineJob.start(decodeJob);
要想确定cb和callbackExecutor的类型,我们还需要一步一步往回走
//特别关注最后两个参数
public synchronized <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)
SingleRequest#onSizeReady
loadStatus =
============================================================================
= 重点关注倒数第二个参数,传入的是this,即SingleRequest对象,其实现了ResourceCallback接口
= 重点关注倒数第一个参数,传入有绑定主线程的Handle的r线程池callbackExectuter
============================================================================
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);
- SingleRequest的onSizeReady中我们确定了cb的类型为SingleRequest对象,另外一个参数的话由于篇幅原因就不一一贴出代码了(都是上文贴过的代码),你可以直接从onSizeReady方法往回看,上面的注释也会提到,最后你会发现这个callbackExecutor其实就是我们一开始提到的含有绑定主线程Handler的线程池。让我们回到最初的地方
EngineJob#onResourceReady
for (final ResourceCallbackAndExecutor entry : copy) {
//回调给ImageViewTarget来展示资源
//entry.cb为singleRequest类型类型
//entry.executor就是含有绑定了主线程的Handler的线程池,即MAIN_THREAD_EXECUTOR
entry.executor.execute(new CallResourceReady(entry.cb));
}
所以我们来看看Executors的mainThreadExecutor方法(忘记的重新看上面的2.2)
private static final Executor MAIN_THREAD_EXECUTOR =
new Executor() {
//绑定主线程的Looper
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
handler.post(command);
}
};
public static Executor mainThreadExecutor() {
return MAIN_THREAD_EXECUTOR;
}
根据Handler机制的相关知识,当调用MAIN_THREAD_EXECUTOR的execute方法后将会在主线程中执行CallResourceReady对象的run方法。所以我们看看CallResourceReady的run方法
显示图片
EngineJob.CallResourceReady#run
public void run() {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
// Acquire for this particular callback.
engineResource.acquire();
======================================
= 重点关注,此时cb为SingleRequest对象
======================================
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
try {
======================================
= 回调,将目标数据回调出去
= 此时的cb为singleRequest类型
======================================
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
又来到了我们熟悉的回调了,此时的cb是SingleRequest类型,我们已经在上文分析过了。所以会调用SingleRequest的onResourceReady方法
SingleRequest#onResourceReady
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
.......
============================
= 重点关注
============================
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
//第一次加载
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
+ dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
+ LogTime.getElapsedMillis(startTime) + " ms");
}
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
//如果在使用时设置listener的话,就会回调其中的onResourceReady
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
======================================
= 展示照片
= 此时的target为DrawableImageViewTarget
=======================================
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
============================
= 通知加载成功
============================
notifyLoadSuccess();
}
这里我们只需要关注target.onResourceReady(result, animation)这句代码,target对象为DrawableImageViewTarget,所以会调用DrawableImageViewTarget的onResourceReady方法,但是因为DrawableImageViewTarget是没有onResourceReady这个方法的,所以应该是在其父类ImageViewTarget中
ImageViewTarget
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
//是否有动画效果
if (transition == null || !transition.transition(resource, this)) {
============================
= 重点关注,静态图
============================
setResourceInternal(resource);
} else {
=======
= gif
=======
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
//调用setResource来展示照片
setResource(resource);
maybeUpdateAnimatable(resource);
}
//此方法为抽象方法,由子类实现,由于分析的是静态图,故实现的子类应该为DrawableImageViewTarget
protected abstract void setResource(@Nullable Z resource);
这里我们以正常的静态图为例子,所以接下来会调用setResourceInternal(resource)方法,然后继续调用setResource(resource)方法来展示图片,setResource在ImageViewTarget为抽象方法,所以我们继续看回子类DrawableImageViewTarget的实现
DrawableImageViewTarget#setResource
protected void setResource(@Nullable Drawable resource) {
//成功展示照片
view.setImageDrawable(resource);
}
小结