Glide源码学习
基本使用
1 | Glide.with(this).load("https://www.baidu.com/123.jpg").into(imageView); |
with
1 | public static RequestManager with(Context context) { |
1 | public RequestManager get(Context context) { |
根据传入的context不同而返回不同的RequestManager,看似重载了很多get方法,但是实际上只区分为applicationCtx和非applicationCtx(Fragment)。下面基于applicationCtx来跟进getApplicationManager(context)
。
1 | private RequestManager getApplicationManager(Context context) { |
即with返回了一个RequestManager对象,RequestManager具体是干什么的后面再说。
load
同样的load也有很多重载方法,我们以String为参数的方法来跟进,懂了一个,其他也一通百通,源码阅读过程切忌沉迷细节。
1 | public DrawableTypeRequest<String> load(String string) { |
fromString()
返回了DrawableTypeRequest的实例,DrawableTypeRequest继承了DrawableRequestBuilder,load方法也没有重写,直接调用的DrawableRequestBuilder的,而DrawableRequestBuilder又继承了GenericRequestBuilder。
1 |
|
最后将返回值向下转型为子类 DrawableTypeRequest
into
还是走的父类方法
1 | //DrawableRequestBuilder.java |
GlideDrawableImageViewTarget
跟进看看这个buildImageViewTarget返回什么
1 |
|
返回的是GlideDrawableImageViewTarget实例,再回到上面的into方法中跟进
1 | public <Y extends Target<TranscodeType>> Y into(Y target) { |
getRequest在父类ViewTarget中实现
1 |
|
这里会对view的Tag做一个检查,如果不是由glide来setTag的话会抛出异常,这也是为什么有Glide时,处理recyclerView的错位问题,我们不能通过直接对ImageView来setTag判断是否错位。
回归正题,首次使用的时候返回的request应该是null,所以就走的下面这一部分核心代码
1 | Request request = buildRequest(target); |
buildRequest
1 | private Request buildRequest(Target<TranscodeType> target) { |
就看最基本情况,没有缩略图,返回一个obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
1 | private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority, |
在这根据一些传入的参数和默认参数构建一个GenericRequest实例。
后面setRequest就略过不提了,然后是lifecycle.addListener(target);
,这个lifecycle结合代码是with中创建RequestManager的时候传入的new ApplicationLifecycle()
,而target是GlideDrawableImageViewTarget
1 | public interface Target<R> extends LifecycleListener{ |
resource初始时为null 暂时略过
runRequest
再来看看requestTracker.runRequest(request);
requestTrack也是构造RequestManager的时候传入一个new RequestTracker();
1 | private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>()); |
上面buildRequest返回的是GenericRequest的实例,跟进
1 |
|
跟进onSizeReady
1 |
|
loaderprovider
其中的loadProvider来自上述load方法中的
1 | //requestManage.java |
可以看到主要在buildProvider中构造了transcoder、dataLoadProvider、modelLoader。
具体方法自己跟进源码,记住不要沉迷细节无法自拔:
transcoder 是 ResourceTranscoder实例
dataLoadProvider 是 DataLoadProvider实例
modelLoader 是 ImageVideoModelLoader实例
返回的是FixedLoadProvider实例
engin.load
理清了loadprovider再回到onSizeReady中
1 |
|
在跟进到engine.load中之前,我们先看下这个核心方法的注释,一个有良心的框架,在重要的方法上都应该好好写一下注释。。
1 | * <p> |
那么就可以把load源码中的部分进行删减,我们就从新开一个load请求这个情况分析
1 | public <T, Z, R> LoadStatus load(/*省略参数*/) { |
逐个分析吧 EngineJob
1 | /** |
DecodeJob看名字就像负责解码的,暂时略过
EngineRunnable
1 | /** |
然后把EngineRunnable放到EngineJob中执行
1 | private final ExecutorService diskCacheService; |
进入到EngineRunnable的run方法中:
1 |
|
最后走到decodeJob来做网络请求
1 | public Resource<Z> decodeFromSource() throws Exception { |
根据上面分析,可以知道这个fetcher是从ImageVideoModelLoader中获取的,返回的是ImageVideoFetcher实例。
跟进ImageVideoFetcher的loadData
streamFetcher.loadData
1 |
|
1 |
|
这个streamFetcher结合初始化loadGeneric
的代码可以知道是HttpUrlFetcher的实例,跟进查看其loadData
方法
1 |
|
可以看到在loadDataWithRedirects
中通过httpUrlConnection来完成网络请求。成功之后就调用getStreamForSuccessfulRequest
1 | private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection) |
将成功请求的io流返回而已。
return ImageVideoWrapper
一路返回到上面说的ImageVideoFetcher的loadData
方法中,继续往下走
1 |
|
返回ImageVideoWrapper到DecodeJob中
1 | private Resource<T> decodeSource() throws Exception { |
再跟进到decodeFromSourceData
===暂时烂尾===
1 | //ImageViewTarget.java |