问题
- 我们正常调用Glide时如何开始的异步加载
- Glide如何与生命周期相关的
简单使用
Glide.with(this).load(R.drawable.test).into(iv_image)
流程解析
Glide.with()
有多个with方法,这里只以参数是context的来举例
//Glide.java
//通过RequestManagerRetriever实例去获取对应context的RequestManager
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
//获取Glide对象中的RequestManagerRetriever实例(RequestManager检索器)
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
//获取Glide的单例
@NonNull
public static Glide get(@NonNull Context context) {
//这个双重锁就可以看出来,Glide是单例的
if (glide == null) {
//这里的GeneratedAppGlideModule是我们自定义的GlideModle,用于修改如缓存池大小的参数
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
//初始化Glide对象,可以自己点进去看一下,里面涉及到了缓存池的初始化等内容,内容比较集中
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
由上面代码可得知,这些类的具体作用为
- Glide:单例,用于统一管理Glide
- RequestManagerRetriever:单例,用于统一管理RequestManager
- RequestManager:未知
而上面的内容则表示Glide.with(context)会根据context来获取一个RequestManager。
我们接下来看看RequestManager怎么来的
RequestManagerRetriever.java
@NonNull
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
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
//其它context其实还是类似Application的调用
return get(((ContextWrapper) context).getBaseContext());
}
}
//在子线程,或者context是属于Application的,则调用到这里
//内部其实是获取一个与Application绑定的RequestManager,变量为applicationManager
return getApplicationManager(context);
}
//以Activity参数的为例
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
//若是在子线程,还是直接会返回applicationManager
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
//注意这里,看方法名貌似会生成一个Fragment
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
//获取一个新的RequestManager实例
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//获取了一个RequestManagerFragment出来
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//从Fragment里取出个RequestManager对象,新创建的是不会有对象的
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
//通过工厂新建一个RequestManager,注意第二个参数传入了Fragment的lifecycle,是为了让RequestManager可以知道Fragment的生命周期
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//这里把RequestManager存入Fragment中
current.setRequestManager(requestManager);
}
//最终返回RequestManager
return requestManager;
}
//获取一个绑定上当前界面的Fragment
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//通过tag去找该Fragment是否已经存在
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//pendingRequestManagerFragments存的是整个进程等待创建的RequestManagerFragment列表
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
//如果我们的父Activity或父Fragment可见,就直接调用onStart回调
current.getGlideLifecycle().onStart();
}
//先存入等待创建列表
pendingRequestManagerFragments.put(fm, current);
//找到了就加到当前FragmentManager上,从而实现生命周期的监听
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//成功add之后,就从等待创建列表里移除。这里通过handler保证线程安全
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
由上面一大串代码可知
- Glide通过创建一个完全透明的Fragment,并监听它的回调,来实现对生命周期的管理
- RequestManager是与FragmentManager一一对应的,即一个Activity/Fragment,都对应一个RequestManager
- 所以RequestManager的作用就是管理在同一个生命周期下的所有请求
Glide.with().load()
这里的load方法就是调用的RequestManager的load方法了,以load一个ResourceId为例
//RequestManager.java
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return asDrawable().load(resourceId);
}
//初始化了一个ResourceType为Drawable.class的RequestBuilder(Request构造器)
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
//asDrawable会先new一个RequestBuilder
return new RequestBuilder<>(glide, this, resourceClass, context);
}
//RequestBuilder.java
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return loadGeneric(resourceId).apply(signatureOf(AndroidResourceSignature.obtain(context)));
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
//load则只是把load里的输入对象存入了RequestBuilder的model中
this.model = model;
isModelSet = true;
return this;
}
从上面代码可知
- load并没有正式发起请求,只是生成了一个request的构造器
- 这个request的构造器包含的信息有输入的对象(这里是资源id),和输出对象的class(这里是Drawable.class)
Glide.with().load().into()
这里是我们实现ImageView展示图片的最后一步,所以请求肯定会在这个方法内发起
//RequestBuilder.java
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
//若ImageView设置了scaleType,Glide也会把它存入这次request的配置中
switch (view.getScaleType()) {
case CENTER_CROP:
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.
}
}
return into(
//这里只是把ImageView和Drawable.class绑定起来生成一个新对象ImageViewTarget便于处理最终结果
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
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慎入,会把自己看晕,我们要了解的是这个buildRequest只是生成了一个SingleRequest实例而已
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//这里的大致意思是如果这个viewTarget已经有一个一样的request请求,且不在运行状态,则直接重新调用它的begin
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
//把ViewTarget的请求清空
requestManager.clear(target);
//把request设置到ImageView的tag上
target.setRequest(request);
//见下
requestManager.track(target, request);
return target;
}
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
//targetTracker是Target的统一生命周期管理类,用来调用target的生命周期方法,里面内容比较单一,可以自己看
targetTracker.track(target);
//见下面的分析,大意就是开始一次request
requestTracker.runRequest(request);
}
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
//正式开始request!
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
//若当前界面未显示或手动暂停了,则加入pendingRequests列表,防止该Request被系统回收
pendingRequests.add(request);
}
}
上面的代码展示了into方法的作用,那么大段
- 通过RequestBuilder对象生成一个Request,分别存入RequestTracker和view中
- 执行这个Request
最后总结一下本文出现的各个类的作用:
- Glide:单例,用于统一管理Glide
- RequestManagerRetriever:单例,用于获取RequestManager
- RequestManager:请求管理器,一个界面对应一个RequestManager
- RequestBuilder:Request的构造者
- Request:我们的一次加载请求
问题解答
- 我们正常调用Glide时如何开始的异步加载?Glide会根据传入的context拿到对应的RequestManager,并根据load传入的资源生成一个Request请求,最后调用Request.begin正式开始这次加载请求(注意我们这次源码分析一直都是在主线程进行的,其实还并没有分析到异步加载的地方)
- Glide如何绑定生命周期的?通过在当前页面add一个透明的Fragment实现的生命周期监听,Fragment在跳转对应生命周期时会回调给ViewTarget