上一篇中 Glide.with(this).load("http://p1.pstatp.com/large/166200019850062839d3").into(iv); 加载图片,load() 方法执行到 RequestManager 中的
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
+ " which there is a registered ModelLoader, if you are using a custom model, you must first call"
+ " Glide#register with a ModelLoaderFactory for your custom model class");
}
return optionsApplier.apply(
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
}
class OptionsApplier {
public <A, X extends GenericRequestBuilder<A, ?, ?, ?>> X apply(X builder) {
if (options != null) {
options.apply(builder);
}
return builder;
}
}
也就是说,load() 返回的对象是 DrawableTypeRequest ,看下它的代码
DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}
构造方法中的泛型 <ModelType> 此时的值是 <String> 类型,次构造方法调用了父类的super()方法,注意,它里面调用了 buildProvider() 方法,
private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass,
Class<R> transcodedClass,
ResourceTranscoder<Z, R> transcoder) {
if (streamModelLoader == null && fileDescriptorModelLoader == null) {
return null;
}
if (transcoder == null) {
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
fileDescriptorModelLoader);
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
}
这里面懵了,泛型太多,没关系,根据 buildProvider() 方法传入的参数,可以辨别 <A, Z, R> 对应的是 <String, GifBitmapWrapper, GlideDrawable> ,这个需要细心点就能发现; streamModelLoader 对应上一篇中的 StreamStringLoader,fileDescriptorModelLoader 暂时认为是null,resourceClass 是 GifBitmapWrapper.class,transcodedClass是 GlideDrawable.class; 继续看这个方法,创建 transcoder 和 dataLoadProvider,都是Glide中的方法返回的对象, modelLoader 是个包装类,封装了两个对象,然后就是 FixedLoadProvider 了,它的构造方法中需要 modelLoader, transcoder, dataLoadProvider 这三个对象。那么 transcoder 和 dataLoadProvider 是怎么来的?还是Glide 的构造方法
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
dataLoadProviderRegistry = new DataLoadProviderRegistry();
StreamBitmapDataLoadProvider streamBitmapLoadProvider =
new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat);
dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider);
FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider =
new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat);
dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider);
ImageVideoDataLoadProvider imageVideoDataLoadProvider =
new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider);
GifDrawableLoadProvider gifDrawableLoadProvider =
new GifDrawableLoadProvider(context, bitmapPool);
dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider);
dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));
dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider());
...
transcoderRegistry.register(Bitmap.class, GlideBitmapDrawable.class,
new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool));
transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class,
new GifBitmapWrapperDrawableTranscoder(
new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)));
...
}
这和上一篇中的 ModelLoader 方法类似,也是先用集合缓存数据,然后根据key值来找相对应的对象,transcoder = glide.buildTranscoder(resourceClass,transcodedClass) 中的形参为 GifBitmapWrapper.class 和 GlideDrawable.class,所以 transcoder 对应的是 GifBitmapWrapperDrawableTranscoder,它里面还包裹了一层 GlideBitmapDrawableTranscoder;dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class, resourceClass) 则 resourceClass 为
GifBitmapWrapper.class,所以 dataLoadProvider 是 ImageVideoGifDrawableLoadProvider, 它构造方法中参数包括 ImageVideoDataLoadProvider,而 ImageVideoDataLoadProvider 的构造方法包括 StreamBitmapDataLoadProvider,它们是聚合关系,一层层的,看看 ImageVideoGifDrawableLoadProvider 的构造
public ImageVideoGifDrawableLoadProvider(DataLoadProvider<ImageVideoWrapper, Bitmap> bitmapProvider,
DataLoadProvider<InputStream, GifDrawable> gifProvider, BitmapPool bitmapPool) {
final GifBitmapWrapperResourceDecoder decoder = new GifBitmapWrapperResourceDecoder(
bitmapProvider.getSourceDecoder(),
gifProvider.getSourceDecoder(),
bitmapPool
);
cacheDecoder = new FileToStreamDecoder<GifBitmapWrapper>(new GifBitmapWrapperStreamResourceDecoder(decoder));
sourceDecoder = decoder;
encoder = new GifBitmapWrapperResourceEncoder(bitmapProvider.getEncoder(), gifProvider.getEncoder());
sourceEncoder = bitmapProvider.getSourceEncoder();
}
这里面又是个封装类 GifBitmapWrapperResourceDecoder,它把形参 bitmapProvider 中的对象封装了一层, getSourceDecoder() 返回的对象就是 GifBitmapWrapperResourceDecoder。
继续回到 DrawableTypeRequest 中的构造方法,创建了 FixedLoadProvider 对象,然后把它当做参数传给了父类 DrawableRequestBuilder,它的构造也同样调用父类方法,继续参数上传到 GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> 中,注意泛型和 FixedLoadProvider 中的泛型是一一对应的,这里是 GenericRequestBuilder<String, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>,DrawableRequestBuilder 类继承
GenericRequestBuilder 时标明了后面三个泛型的对象类型,这个可以先记住,下面分析会用到。
Glide.with(this).load("http://p1.pstatp.com/large/166200019850062839d3").into(iv) 的 into() 方法,是在 DrawableRequestBuilder 中,它调用了父类 GenericRequestBuilder 中的方法,
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
第一行是校验是否在主线程,我们只看最后一行, buildImageViewTarget() 方法最终调用 ImageViewTargetFactory 中的方法
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new GlideDrawableImageViewTarget(view);
} else if (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz
+ ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
此刻传入的transcodeClass类型是 GlideDrawable.class,所以返回的是 GlideDrawableImageViewTarget 对象,继续看 into() 方法
public <Y extends Target<TranscodeType>> Y into(Y target) {
...
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);
return target;
}
注意两行代码 buildRequest(target) 和 requestTracker.runRequest(request),
private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}
private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
...
} else {
// Base case: no thumbnail.
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(...);
}
request 就是 GenericRequest 对象;requestTracker 是哪里来的呢?看代码发现,它是 RequestManager 的构造方法new出来的 RequestTracker,它里面代码比较简单,有两个集合,装的是请求的 request 和 待请求的 request, requestTracker.runRequest(request) 方法为
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
RequestManager 也会受 Lifecycle 的回调,在 Activity 中,Activity 切入前后台时,RequestManager 中的onStart()和onStop()方法会被调用
@Override
public void onStart() {
resumeRequests();
}
public void resumeRequests() {
Util.assertMainThread();
requestTracker.resumeRequests();
}
@Override
public void onStop() {
pauseRequests();
}
public void pauseRequests() {
Util.assertMainThread();
requestTracker.pauseRequests();
}
因此,requestTracker.runRequest(request) 方法中的代码就好理解了,request.begin() 执行的是 GenericRequest 的 begin() 方法
@Override
public void begin() {
...
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
...
}
我们上述代码,没有指定图片大小,所以会执行 target.getSize(this) 代码,它里面经历一些计算然后回调到本类中的 onSizeReady(overrideWidth,overrideHeight) 方法,target.onLoadStarted() 方法则是加载占位图,看下 ImageViewTarget 中的方法就明白了。这里说下 target.getSize() 方法,它是在 ViewTarget 中,用 SizeDeterminer 类中的方法,这里面会有些逻辑换算,有个技巧点,那就是添加集合存储cb回调,用 ViewTreeObserver 监听view绘制前的回调方法,重新获取view的宽和高,然后回调到 GenericRequest 中的 onSizeReady() 方法中
@Override
public void onSizeReady(int width, int height) {
...
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Failed to load model: \'" + model + "\'"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
loadedFromMemoryCache = true;
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
...
}
终于到这一步了,看到 modelLoader 和 dataFetcher,modelLoader 是 FixedLoadProvider 中的 modelLoader,是在 DrawableTypeRequest 的 buildProvider()方法中创建的 ImageVideoModelLoader,dataFetcher 获取的对象是封装了HttpUrlFetcher 的 ImageVideoFetcher 对象;看下 ImageVideoModelLoader 的方法
@Override
public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {
DataFetcher<InputStream> streamFetcher = null;
if (streamLoader != null) {
streamFetcher = streamLoader.getResourceFetcher(model, width, height);
}
...
if (streamFetcher != null || fileDescriptorFetcher != null) {
return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);
} else {
return null;
}
}
它封装的 streamLoader 就是 StreamStringLoader 对象,getResourceFetcher(model, width, height) 返回的 streamFetcher 是 HttpUrlFetcher,然后把它封装到 ImageVideoFetcher 中,为什么是 HttpUrlFetcher,这就是上一篇中重点分析的东西。transcoder 则是上面分析的 FixedLoadProvider 构造方法中第二个参数transcoder 即 GifBitmapWrapperDrawableTranscoder 对象;engine 则是默认的 Engine 对象;接下来是Engine 的 load()方法了
public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
...
final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
...
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
...
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(runnable);
...
return new LoadStatus(cb, engineJob);
}
一开始通过 fetcher 获取到 id,然后用一系列相关参数传入 EngineKey 中,这个 key 就是该图片的唯一标示,它是缓存模块的一个关键,只要它里面的参数有任何一遍变化了,则会认为是新图片,就会重新创建并缓存;loadFromCache() 和 loadFromActiveResources() 是从缓存中获取,如果有值,直接回调 cb 的方法,这个放到下篇缓存的文章中,这篇先继续说网络,继续往下看,这里有三个对象 EngineJob、DecodeJob 和 EngineRunnable,EngineRunnable 实现了 Runnable 接口,耗时操作比如从本地读取数据或者从网络获取数据,都是从这里面执行; DecodeJob 更像是中转器的控制类,负责逻辑调用;EngineJob 则是提供线程池及子线程切换到主线程并把值给回调回去,回调 cb 是 ResourceCallback,cb 通过 engineJob.addCallback(cb) 被添加进去,engineJob.start(runnable) 则是执行子线程,看看它的方法
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
future = diskCacheService.submit(engineRunnable);
}
@Override
public void submitForSource(EngineRunnable runnable) {
future = sourceService.submit(runnable);
}
这里的 diskCacheService 和 sourceService 的源头是 GlideBuilder 中的 createGlide() 方法,都是 FifoPriorityThreadPoolExecutor,里面核心线程数见代码;继续看 EngineRunnable 类,构造方法中 stage = Stage.CACHE,再看看 run() 方法
@Override
public void run() {
...
Exception exception = null;
Resource<?> resource = null;
try {
resource = decode();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
exception = e;
}
...
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();
} else {
return decodeFromSource();
}
}
private boolean isDecodingFromCache() {
return stage == Stage.CACHE;
}
此方法中,会执行 decode() 方法,此时 isDecodingFromCache() 为true,执行 decodeFromCache(),这里会通过 DecodeJob 查找磁盘缓存,咱们默认找不到,返回的是 null,接下来就会执行 onLoadFailed(exception) ,
private void onLoadFailed(Exception e) {
if (isDecodingFromCache()) {
stage = Stage.SOURCE;
manager.submitForSource(this);
} else {
manager.onException(e);
}
}
这里 isDecodingFromCache() 仍为true,改变 stage 的状态值,这里 manager 就是构造方法传进来的 EngineJob engineJob 对象,所以这次就是 sourceService 这个线程池执行 runnable 本身了,再次看 run() 方法,这次是 decodeFromSource() 方法
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
DecodeJob:
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
这里返回的就是我们需要的值,先看第一行代码
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority);
...
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
好吧,看到 fetcher.loadData(priority) 这行代码,fetcher 是 ImageVideoFetcher 类型,是一个封装类,所以 fetcher.loadData(priority) 执行的是 ImageVideoFetcher 的 loadData(Priority priority) 方法
@Override
public ImageVideoWrapper loadData(Priority priority) throws Exception {
InputStream is = null;
if (streamFetcher != null) {
try {
is = streamFetcher.loadData(priority);
} catch (Exception e) {
...
}
}
...
return new ImageVideoWrapper(is, fileDescriptor);
}
网络请求就是这一刻触发了,streamFetcher 是 HttpUrlFetcher 类型,返回的 data 是ImageVideoWrapper类型,里面封装了InputStream流。然后调用 decodeFromSourceData(data) 方法进行数据的解码
private Resource<T> decodeFromSourceData(A data) throws IOException {
final Resource<T> decoded;
if (diskCacheStrategy.cacheSource()) {
decoded = cacheAndDecodeSourceData(data);
} else {
long startTime = LogTime.getLogTime();
decoded = loadProvider.getSourceDecoder().decode(data, width, height);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded from source", startTime);
}
}
return decoded;
}
这里有个缓存策略,是保存原图、转换后的图还是都保存,默认是缓存转换后的图,这里走到 else 里面, loadProvider.getSourceDecoder() 代码中 loadProvider 是LoadProvider类型 ChildLoadProvider,它封装了 FixedLoadProvider,执行的还是 FixedLoadProvider 中的方法,然后调用ImageVideoGifDrawableLoadProvider中的 getSourceDecoder() 方法,返回的 sourceDecoder 是个 GifBitmapWrapperResourceDecoder 类型,decode(data,width, height) 方法则比较有意思,就是一串线,GifBitmapWrapperResourceDecoder(ImageVideoGifDrawableLoadProvider) --》 ImageVideoDataLoadProvider --》 StreamBitmapDataLoadProvider --> StreamBitmapDecoder --> Downsampler,在 GifBitmapWrapperResourceDecoder 中调用,Downsampler 中返回 Resource<Bitmap>,然后再封装一层变为 GifBitmapWrapper,再创建 GifBitmapWrapperResource ,继续回到 DecodeJob 中的 decodeFromSource()方法,
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
此时 decoded 为 GifBitmapWrapperResource,调用 transformEncodeAndTranscode(decoded) 进行图片的转换,这里先忽略,后面的文章会分析。回到EngineRunnable中的 run() 方法,获取到了值,就执行 onLoadComplete(resource) 方法
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
看看 EngineJob 中的 onResourceReady() 方法,这里用 Handler 发送一条消息,切回了主线程,执行了 handleResultOnMainThread() 方法
private void handleResultOnMainThread() {
...
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource);
}
}
...
}
看回调,这里的 cb 是在 Engine 的 load() 方法中添加的,执行的是 GenericRequest 中的 onResourceReady(Resource<?> resource) 方法,最终执行了重载的方
法
private void onResourceReady(Resource<?> resource, R result) {
...
if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,
isFirstResource)) {
GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);
target.onResourceReady(result, animation);
}
...
}
我们用 Glide 的时候可以设置加载图片成功或失败的回调,就是这里执行成功的回调,如果返回值是true,则会被消耗掉;如果设置为false或者没设置监听回调,则会执行 target.onResourceReady(result, animation) 的方法,这里 target 是 GlideDrawableImageViewTarget,
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
...
super.onResourceReady(resource, animation);
this.resource = resource;
resource.setLoopCount(maxLoopCount);
resource.start();
}
@Override
protected void setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
这里面的代码比价好理解,先调用父类的方法,父类中会调用 setResource() 方法,就这样加载图片了。