本文将介绍下面三个方法的执行流程
Glide.with(this).load(url).into(imageView);
With
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
with()用来接收一个Context对象,可以直接是Context,也可以是Activity,Fragment,View;getRetriever()
会获取一个RequestManagerRetriever
对象,再通过get()
拿到一个RequestManager
对象;
至此我们可以知道Context是被封装在RequestManager中的,看一下get对于Context处理的逻辑:
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
在get()中,会根据传入的Context参数的类型分为两种,一种是Application类型,还有一种是非Application类型(Activity,Context);
1. 如果Context是Application类型:
/**
* The top application level RequestManager.
*/
private volatile RequestManager applicationManager;
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
如果我们在with()中传入的是一个Application,或者我们在子线程使用Glide,就会通过ApplicationLifecycle,Application Context
去构造一个RequestManager,这中情况下,Glide的生命周期是和App绑定的;
2. 如果是非Application类型的Context
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
public class SupportRequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
unregisterFragmentWithRoot();
}
}
在这种情况下,会通过Activity/Fragment获取一个FragmentManager
对象,然后去创建一个空的fragment(SupportRequestManagerFragment ),这个Fragment是不可见的,它的内部会设置一个接口,用于监听这个Fragment的生命周期,在RequestManagerWraper中,将这个不可见的Fragment同我们的界面进行绑定,那么这个不可见的Fragment就和我们的界面生命周期一致了,这样Glide就可以自动感知调用它的Activity/Fragment的生命周期了;
load
with()返回的是一个RequestManager对象,所以load是由它调用的;
load也进行了很多重载,(Bitmap,Uri,File,byte[]),这里只分析平时使用的最多的一种情况:
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
这里主要是创建了一个RequestBuilder
对象
into
在分析into前,先理清楚几个核心Api的作用:
-
RequestManager:绑定管理生命周期
-
RequestBuilder:构建Request请求,构建Target
-
Target:into方法会返回一个Target,Target是一个Glide可以加载图片资源的具有生命周期的目标,有很多实现类,这里介绍一个常见的的实现类:
-
BitmapImageViewTarget:
glide可以加载一个bitmap资源到imageView上;
- Request:加载图片的请求,具体有三个实现类:
-
SingleRequest:
负责调用Engine执行请求,将结果展示在Target上 -
ErrorRequestCoordinator:
主要用来处理加载失败error的场景; -
ThumbnailRequestCoordinator:
用来协调两个请求,因为有的请求需要同时加载原图和缩略图
into:
RequestBuilder
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
...
return into(
glideContext.buildImageViewTarget(view, transcodeClass), // 创建ImageViewTarget
/*targetListener=*/ null,
requestOptions);
}
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
// 分析1
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
if (!Preconditions.checkNotNull(previous).isRunning()) {
// 分析2
previous.begin();
}
return target;
}
}
在我们调用into(imageView)
后,会通过这个imageView创建一个ImageViewTarget对象,然后在构建一个Request对象;
- 通过ImageViewTarget构建Request对象
- 调用Request的begin(),让Engine处理Request;
SingleRequest
public 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 void onSizeReady(int width, int height) {
...
loadStatus = engine.load(...);
}
如果Imageview还没有绘制好,那么我们的Request.begin()是不会去执行的,ImageViewTarget会注册View 的OnPreDrawListener
事件,在View准备好后,会调用onSizeReady()
剩下的工作都是交给Engine来完成的,Engine的事情比较多,所以Engine的逻辑图另外再画一张
Engine
public <R> LoadStatus load(...) {
...
// 创建 EngineJob
EngineJob<R> engineJob = engineJobFactory.build(...);
// 创建 DecodeJob
DecodeJob<R> decodeJob = decodeJobFactory.build(...);
}
engineJob.addCallback(cb);
// 启动decodeJob
engineJob.start(decodeJob);
在Engine的load中创建了EngineJob,DecodeJob;
-
EngineJob:
用于开启DecodeJob,管理load过程的回调
(注释是这么说的: manages a load by adding and removing callbacks ) DecodeJob:
- 从缓存或数据源中加载原始数据:decoding resources either from cached data or from the original source
- 通过解码器转换为相应的资源类型:applying transformations and transcodes
EngineJob
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
DecodeJob是一个Runnable任务,EnginJob将其提交给了线程池,所以我们直接看它的run()即可:
DecodeJob:
public void run() {
try {
...
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;
}
}
/**
* Why we're being executed again.
*/
private enum RunReason {
/** The first time we've been submitted. */
INITIALIZE,
/**
* 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
* process the data.
*/
DECODE_DATA,
}
在第一种情况中,首先调用了getNextGenerator()
获得一个DataFetcherGenerator
对象,DataFetcherGenerator 是一个接口,有三个具体的实现:
- ResourceCacheGenerator: 资源文件
- DataCacheGenerator: 缓存文件
- SourceGenerator: 网络文件
DecodeJob:
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
}
在runGenerators中会调用startNext(),因为第一次会从网络加载,看一下SourceGenerator的实现
SourceGenerator
private volatile ModelLoader.LoadData<?> loadData;
private final DecodeHelper<?> helper;
@Override
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()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 分析1
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
- 调用loadData内部的DataFetcher的loadData(),这里是发起网络请求的地方:
HttpUrlFetcher.load()
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
// 网络数据流获取成功后的回调
callback.onDataReady(result);
} catch (IOException e) {
callback.onLoadFailed(e);
}
}
这里通过loadDataWithRedirects()
获取一个流,再通过一个回调通知上层网络数据获取到了,在loadDataWithRedirects()中,使用的HttpURLConnection;
这个回调是通知SourceGenerator的,因为上文分析1那边传了this
SourceGenerator:
public void onDataReady(Object data) {
// 写入disk缓存
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
// We might be being called back on someone else's thread. Before doing anything, we should
// reschedule to get back onto Glide's thread.
cb.reschedule();
} else {
// 回调给上一层
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
这个回调时在DecodeJob中回调的:
DecodeJob:
接受到网络数据的stream后,在DecodeJob中的回调逻辑:调用decodeFromRetrievedData()
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
...
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
try {
decodeFromRetrievedData();
}
}
}
private void decodeFromRetrievedData() {
...
Resource<R> resource = null;
try {
// 分析1
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
// 分析2
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
decodeFromData()这个方法,调了很多decode 相关的代码,这里就不贴了,最后调用了DecodePath类的transcoder接口
DecodePath:
private final ResourceTranscoder<ResourceType, Transcode> transcoder;
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
这个ResourceTranscoder
接口的实现类:
看名称应该可以大概知道和bitmap,gif的解码有关系;decode操作会生成一个BitmapResource对象,在这个BitmapResource中会有一个Bitmap对象;
-
分析1:
主要是对网络流进行解码获取Bitmap对象 -
分析2:
解码完成后,回调上层接口
在DecodeJob完成解码后调用了回调是EngineJob的onResourceReady()
:
EngineJob
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
this.resource = resource;
this.dataSource = dataSource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget(); // 发出handler
}
在回调中发了一个Handler消息;
EngineJob
case MSG_COMPLETE:
job.handleResultOnMainThread();
break;
@Synthetic
void handleResultOnMainThread() {
stateVerifier.throwIfRecycled();
if (isCancelled) {
resource.recycle();
release(false /*isRemovedFromQueue*/);
return;
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
engineResource.acquire();
// 分析1
listener.onEngineJobComplete(this, key, engineResource);
for (int i = 0, size = cbs.size(); i < size; i++) {
ResourceCallback cb = cbs.get(i);
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
// 分析2
cb.onResourceReady(engineResource, dataSource);
}
}
// 释放资源
engineResource.release();
release(false /*isRemovedFromQueue*/);
}
- EngineJob也会掉一个上层接口,这个接口回调到了Engine 中:
Engine:
public void onEngineJobComplete(EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
Util.assertMainThread();
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null) {
resource.setResourceListener(key, this);
if (resource.isCacheable()) {
activeResources.activate(key, resource);
}
}
jobs.removeIfCurrent(key, engineJob);
}
- 分析2:回调
onResourceReady
接口,这个回调走到了SingleRequest
SingleRequest:
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
...
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
// 分析1
target.onResourceReady(result, animation);
}
}
notifyLoadSuccess();
}
- 分析1:在这边调用了Target接口的onResourceReady(),Target接口上文有介绍,我们这里看一下Target接口的实现类ImageViewTarget类的
onResourceReady()
是如何处理的:
ImageViewTarget
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
/**
*这里省略了中间方法的传递,最终调用:
*/
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
最终调用ImageView的setImageBitmap()设置bitmap;
Engine的逻辑看了一周终于走通了,本文参考文章:
网友评论