深入主流框架源码,有利于思维拓展,以及遇到问题能究其根本,所以今天就来扒一扒Glide的基本主线。
Glide框架之所有受欢迎,一是因为它的加载支持生命周期管理,二是支持gif加载,三是占用内存小(默认配置图片编码格式为rgb565),内部使用了多级缓存。但是目前也发现有缺点,实际应用中发现对于gif的支持不是特别好,有时候帧数会出一些问题。
惯例,先说依赖配置:implementation'com.github.bumptech.glide:glide:4.7.1'
以下是基本使用代码,先看看Glide.with()方法都干了些啥
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
Preconditions.checkNotNull(context, "You cannot start a load on a not yet attached View or a Fragment where getActivity() returns null (which usually occurs when getActivity() is called before the Fragment is attached or after the Fragment is destroyed).");
return get(context).getRequestManagerRetriever();
}
@NonNull
public static Glide get(@NonNull Context context) {
if (glide ==null) {
Class var1 = Glide.class;
synchronized(Glide.class) {
if (glide ==null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(), use the provided Glide instance instead");
}else {
isInitializing =true;
initializeGlide(context);
isInitializing =false;
}
}
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
//以上非关键代码注释
Glide glide = builder.build(applicationContext);
//以下非关键代码注释
Glide.glide = glide;
}
从以上调用链可以看出,with方法在Glide的initializeGlide中,创建了Glide类中的静态单例对象glide,然后with方法里面第一个函数getRetriever(activity)返回的是一个RequestManagerRetriever,这个是啥,暂时先不管,解析来看调用的第二个函数,RequestManagerRetriever的get方法。这里会调用supportFragmentGet方法,
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return this.get(activity.getApplicationContext());
}else {
assertNotDestroyed(activity);
androidx.fragment.app.FragmentManager fm = activity.getSupportFragmentManager();
return this.supportFragmentGet(activity, fm, (Fragment)null, isActivityVisible(activity));
}
}
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull androidx.fragment.app.FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current =this.getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager ==null) {
Glide glide = Glide.get(context);
requestManager =this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
从RequestManagerRetriever#supportFragmentGet这个方法以及函数内部调用的第一个方法getSupportRequestManagerFragment可以看出,这里创建了一个SupportRequestManagerFragment,并且添加到了activity,并且在这里绑定了一个RequestManager,这2个玩意,其实就是Glide能根据生命周期管理请求的关键东东,后面会说。
到这里先总结一下,Glide.with做了几件事情:
1. 实例化了Glide对象
2.创建了一个名为SupportRequestManagerFragment的无UI的Fragment,与我们的activity进行关联,并且为SupportRequestManagerFragment设置了一个名为RequestManager的对象
--------------------------------------------------------------------------------------------
接下来再看load方法,load方法构建了一个RequestBuilder,暂时先不看,我们先看下一个方法,也就是into(设置到某个Imageview)上,看源码
@NonNull
public ViewTargetinto(@NonNull ImageView view) {
//上面是一些请求配置项,暂不看
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
private
>Y into( @NonNull Y target,
@Nullable RequestListener
targetListener, @NonNull RequestOptions options) {
//省略。。。
//这里buildRequest构建了一个Request对象,深入追踪会发现,实际创建的是一个叫做SingleRequest的对象,由于代码调用比较深,这里就不一一贴出来了
Request request = buildRequest(target, targetListener, options);
//省略。。。
//这里是关键方法,这里调用了RequestManager的track方法,内部调用了RequestTracker的runRequest方法传进去的就是刚才构建的Request(实际是SingleRequest)
requestManager.track(target, request);
return target;
}
下面我们看下RequestTracker类的runRequest干了些啥。。。
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
}else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
RequestTracker这个类,看到里面管理了2个集合,一个是requests,一个是pendingRequests,有没有感觉似曾相识的感觉,没错,okhttp内部也有自己维护的队列(运行中队列,待执行队列),不过这里是的维护方式是有区别的,我们后面说。这里runRequest方法,把singleRequet添加到了requests集合中,判断如果isPaused,则调用Request的begin方法,否则添加到pendingRequests中,这里isPaused猜测应该是跟页面生命周期相关的字段,看下isPause的字段都在哪些地方有赋值,{pauseRequests,pauseAllRequests,resumeRequests},看下这些方法都是在哪些地方有调用
发现没有,又回到了RequestManager的这个类来了,刚才我们说到了,Glide创建的无UI的SupportRequestManagerFragment,里面也塞了一个RequestManger,这里是不是可以认为Glide的生命周期维护是有Activity传递给SupportRequestManagerFragment,SupportRequestManagerFragment再传递给RequestManager呢?看一下RequestManager的继承实现关系,实现了LifecycleListener接口,然后在SupportRequestManagerFragment这个Fragment类中寻找相关线索,发现创建的时候有个ActivityFragmentLifecycle这个玩意,这个玩意在SupportRequestManagerFragment的onStart/onStop/onDestory中都有调用,但是这个东西跟我们的RequestManager有什么关系呢?我们最终不是调用的是它吗,继续查看ActivityFragmentLifecycle,发现它有个addListener方法,看下它的调用地方,发现了什么,原来在RequestManager构建的时候就把它自己丢给了ActivityFragmentLifecycle,是不是现在一瞬间就清晰了。Activity的生命周期变化传递给了SupportRequestManagerFragment,SupportRequestManagerFragment将变化传递给了ActivityFragmentLifecycle,ActivityFragmentLifecycle将变化最终给到了RequestManager,然后RequestManager最终调用到了RequestTracker的resumeRequests/pauseRequests。
刚才上面提到过Glide的RequestTracker里面维护的2个集合跟Okhttp中Dispatcher所处理的方式不一样,Okhttp是任务执行完后会执行finish方法,判断运行中队列个数以及待执行队列的情况,进行任务转移,而Glide是在页面onStop的时候直接就把所有的请求都给停止了,然后在onStart的时候,把那些没有完成或者失败的请求再次开始请求。
上面只提到了Glide的调用链,基本思路,以及生命周期的管理如何实现,但是最终的请求,我们还没有追踪到,就是SingleRequest的begin方法,这个方法后面的逻辑涉及到后面的多级缓存以及相求相关,这里简单梳理一下
SignleRequest#begin()->SignleRequest#onSizeReady(overrideWidth, overrideHeight); -> engine.load(***)这个方法里面涉及到缓存读取(loadFromActiveResources/loadFromCache),由于时间关系,凌晨一点多了,后面逻辑有时间再补充,白天上班撸码,晚上还要回来学习复习巩固知识,时间有点不够用