前面文章分析到buildRequest方法,现在继续看
buildRequest方法,调用了buildRequestRecursive方法
private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
isThumbnailBuilt = false;
return buildRequestRecursive(target, null);
}
buildRequestRecursive方法,前面两个if判断都是判断是否设置了缩略图需要,调用了thumbnai两个方法走两个if,
private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != null) {
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a thumbnail, "
+ "consider using clone() on the request(s) passed to thumbnail()");
}
// Recursive case: contains a potentially recursive thumbnail request builder.
if (thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) {
thumbnailRequestBuilder.animationFactory = animationFactory;
}
if (thumbnailRequestBuilder.priority == null) {
thumbnailRequestBuilder.priority = getThumbnailPriority();
}
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !Util.isValidDimensions(thumbnailRequestBuilder.overrideWidth,
thumbnailRequestBuilder.overrideHeight)) {
thumbnailRequestBuilder.override(overrideWidth, overrideHeight);
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}
不过最终都会调用obtainRequest方法,该方法直接调用GenericRequest类的obtain方法
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}
GenericRequest 的 obtain方法,该方法从REQUEST_POOL队列里面拿请求,如果没有则生成
public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
...省略参数) {
@SuppressWarnings("unchecked")
//从队列里面拿出一个请求
GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
//没有则直接生成一个
if (request == null) {
request = new GenericRequest<A, T, Z, R>();
}
//省略一系列参数
request.init(...);
return request;
}
调用了GenericRequest的init方法,该方法就是直接把参数赋值到对象里面
继续看into方法。构建request后, 把request丢进了requestTracker执行
public <Y extends Target<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
throw new IllegalArgumentException("You must pass in a non null Target");
}
if (!isModelSet) {
throw new IllegalArgumentException("You must first set a model (try #load())");
}
//获取target里面的request。清楚和回收
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
//构建requeset
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);
return target;
}
RequestTracker 的runRequest方法,把request放入requests集合,如果已经是暂停状态了,则放入pendingRequests集合,否则执行begin方法。至于什么时候是暂停状态,看什么时候调用了pauseRequests方法。
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
//调用request的begin方法
request.begin();
} else {
pendingRequests.add(request);
}
}
Request的begin方法。如果前面调用了thumbnai方法,则会走onSizeReady,否则走else语句,我们没设置,看getSize方法
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
onException(null);
return;
}
//设置状态
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
getSize在ViewTarget里面实现,逻辑也很清晰,去获取控件的宽高,如果获取不到,则利用ViewTreeObserver的监听去获取, 而我们在Activity的onCreate方法里面如果想获取控件的宽高,一般也会如此。最后获取到宽高后都会调用Request的onSizeReady方法
public void getSize(SizeReadyCallback cb) {
int currentWidth = getViewWidthOrParam();
int currentHeight = getViewHeightOrParam();
if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
cb.onSizeReady(currentWidth, currentHeight);
} else {
// We want to notify callbacks in the order they were added and we only expect one or two callbacks to
// be added a time, so a List is a reasonable choice.
if (!cbs.contains(cb)) {
cbs.add(cb);
}
if (layoutListener == null) {
final ViewTreeObserver observer = view.getViewTreeObserver();
layoutListener = new SizeDeterminerLayoutListener(this);
observer.addOnPreDrawListener(layoutListener);
}
}
}
GenericRequest的onSizeReady方法,宽高是我们前面获取到的,sizeMultiplier默认是1,关键代码是嗲用了engine的load方法,这个方法好像才是去真正加载资源的地方。
@Override
public void onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Got null fetcher from model loader"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
//总是先从内存缓存中获取
loadedFromMemoryCache = true;
//调用Engine的load方法
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
Engine的load方法,生成了一个DecodeJob对象放入EngineJob对象,并放入LoadStatus里面,返回。
//省略参数
public <T, Z, R> LoadStatus load(...) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
//1 从缓存中获取
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
//获取到,回调。从缓存中获取到后放入activeResources集合
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//2 从activeResources集合中获取
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//缓存和activeResources中都没有,根据key查询是否已经生成了EnginJob。
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
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);
//3 把runnable提交到线程池执行
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
先看注释1 ,从缓存中加载,通过用remove方法获取,那么缓存只缓存一次,从缓存中获取后,把缓存中的又放入activeResources集合。调用acquire方法只是统计它的调用次数。当内存不够时根据调用频率释放内存。
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
cached.acquire();
activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
}
return cached;
}
@SuppressWarnings("unchecked")
private EngineResource<?> getEngineResourceFromCache(Key key) {
Resource<?> cached = cache.remove(key);
final EngineResource result;
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
// Save an object allocation if we've cached an EngineResource (the typical case).
result = (EngineResource) cached;
} else {
result = new EngineResource(cached, true /*isCacheable*/);
}
return result;
}
注释2 ,从activeResources集合中获取,获取到,更新调用频率。获取不到,则删除key.因为value用的弱引用。可能被回收了,这样key也无效了。这样看它真是的缓存就是activeResources集合了。
private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> active = null;
WeakReference<EngineResource<?>> activeRef = activeResources.get(key);
if (activeRef != null) {
active = activeRef.get();
if (active != null) {
active.acquire();
} else {
activeResources.remove(key);
}
}
return active;
}
注释3,提交到线程池。那就看run方法了。
//执行线程池
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
future = diskCacheService.submit(engineRunnable);
}
EngineRunnable实现了Runnable接口,因此直接看run方法,里面主要调用了decode()方法,然后再回调。
@Override
public void run() {
if (isCancelled) {
return;
}
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 (isCancelled) {
if (resource != null) {
resource.recycle();
}
return;
}
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
看decode方法,判断是否从缓存
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();
} else {
return decodeFromSource();
}
}
由于我们是没加载过,因此走else分支的decodeFromSouce方法
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
调用DecodeJob的decodeFromSource方法
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
调用了fetcher方法的loadData方法,由于前面我们知道这个类是个HttpUrlFetcher类,应该去该类查看loadData方法
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
HttpUrlFetcher的loadData方法。内部调用了loadDataWithRedirects方法,里面有我们熟悉的HttpURLConnection 网络请求,看了这么久终于看到网络请求的代码了,该方法如果请求成功返回InputStream,如果失败还会重试4次。
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/);
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl) throws IOException {
//如果次数大于5次,返回错误
if (redirects >= MAXIMUM_REDIRECTS) {
throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new IOException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
urlConnection = connectionFactory.build(url);
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
stream = urlConnection.getInputStream();
return stream;
} else if (statusCode / 100 == 3) {
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new IOException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl, redirects + 1, url);
} else {
if (statusCode == -1) {
throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
}
throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
}
}
继续看该方法, 服务器返回的数据在InputStream里面,然后在调用decodeFromSourceData,去解析InputStream。
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
decodeFromSourceData方法,调用了decode方法去解析。当我们点进decode方法时,发现又是一个接口,还带两泛型。也一样要知道它的实现类是哪个,才能知道它最终的实现方法。查找实现类和我们前面的查找fetcher类的方式一样。这里我们就不再和前面一样去贴代码,知道这里最终调用的实现类是StreamBitmapDecoder的decode方法,
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;
}
StreamBitmapDecoder,这个类把解析工作委托给Downsampler类了
public class StreamBitmapDecoder implements ResourceDecoder<InputStream, Bitmap> {
...
@Override
public Resource<Bitmap> decode(InputStream source, int width, int height) {
Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);
return BitmapResource.obtain(bitmap, bitmapPool);
}
...
}
decode方法里面调用了downsampleWithSize方法,而downsampleWithSize方法会调用decodeStream方法,decodeStream里面调用我们熟悉的BitmapFactory.decodeStream方法。当然它里面对流做了优化处理。具体细节可详细参考decode方法。这里我们只是查看其大概流程。细节不作深入研究。
public Bitmap decode(InputStream is, BitmapPool pool, int outWidth, int outHeight, DecodeFormat decodeFormat) {
...
final Bitmap downsampled =
downsampleWithSize(invalidatingStream, bufferedStream, options, pool, inWidth, inHeight, sampleSize,
decodeFormat);
...
Bitmap rotated = null;
//判断是否需要旋转
if (downsampled != null) {
rotated = TransformationUtils.rotateImageExif(downsampled, pool, orientation);
if (!downsampled.equals(rotated) && !pool.put(downsampled)) {
downsampled.recycle();
}
}
return rotated;
...
}
最终也是调用了BitmapFactory.decodeStream方法
private static Bitmap decodeStream(MarkEnforcingInputStream is, RecyclableBufferedInputStream bufferedStream,
BitmapFactory.Options options) {
...
final Bitmap result = BitmapFactory.decodeStream(is, null, options);
...
return result;
}
@Override
public Resource<Bitmap> decode(InputStream source, int width, int height) {
Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);
return BitmapResource.obtain(bitmap, bitmapPool);
}
当这个方法执行后,终于拿到我们需要的Bitmap对象了。继续回到Decode的decodeFromSource方法。
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
long startTime = LogTime.getLogTime();
//如果需要对bitmap进行处理,则处理
Resource<T> transformed = transform(decoded);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transformed resource from source", startTime);
}
//写入文件缓存
writeTransformedToCache(transformed);
startTime = LogTime.getLogTime();
//把Bitmap转换为drawable
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from source", startTime);
}
return result;
}
Glide里面,其中decodedClass是个GifBitmapWrapper类型,transcodedClass是个GlideDrawable类型
<Z, R> ResourceTranscoder<Z, R> buildTranscoder(Class<Z> decodedClass, Class<R> transcodedClass) {
return transcoderRegistry.get(decodedClass, transcodedClass);
}
在Glide的构造器里面,已经把对应的ResourceTranscoder实现类提前放入map集合中,根据前面两个参数的Class类型获取到后面对应的类,这里我们获取到的是GifBitmapWrapperDrawableTranscoder类,
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class,
new GifBitmapWrapperDrawableTranscoder(
new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)));
...
}
由前面我们分析到transcode方法时,调用的是GifBitmapWrapperDrawableTranscoder类的transcode方法。
private Resource<Z> transcode(Resource<T> transformed) {
if (transformed == null) {
return null;
}
return transcoder.transcode(transformed);
}
因此我们看GifBitmapWrapperDrawableTranscoder 的transcode方法
@Override
public Resource<GlideDrawable> transcode(Resource<GifBitmapWrapper> toTranscode) {
GifBitmapWrapper gifBitmap = toTranscode.get();
Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource();
final Resource<? extends GlideDrawable> result;
if (bitmapResource != null) {
result = bitmapDrawableResourceTranscoder.transcode(bitmapResource);
} else {
result = gifBitmap.getGifResource();
}
// This is unchecked but always safe, anything that extends a Drawable can be safely cast to a Drawable.
return (Resource<GlideDrawable>) result;
}
实际还是调用了bitmapDrawableResourceTranscoder的transcode方法,
继续查看
@Override
public Resource<GlideBitmapDrawable> transcode(Resource<Bitmap> toTranscode) {
GlideBitmapDrawable drawable = new GlideBitmapDrawable(resources, toTranscode.get());
return new GlideBitmapDrawableResource(drawable, bitmapPool);
}
返回一个GlideBitmapDrawableResource对象。
最终会调用transcode方法,调用transcoder.transcode();而这个transcoder哪里被赋值的呢?
private Resource<Z> transcode(Resource<T> transformed) {
if (transformed == null) {
return null;
}
return transcoder.transcode(transformed);
}
在GenericRequest的onSizeReady方法里,可以看到是从loadProvider里面获取到的这个transcoder对象。
@Override
public void onSizeReady(int width, int height) {
...
//从loadProvider对象里面获取的transcoder对象
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
...
loadedFromMemoryCache = true;
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
如果load到资源,则会调用回调ResourceCallback 的onResourceReady方法,也就是GenericRequest的onResourceReady方法
public <T, Z, R> LoadStatus load(...) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
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);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
...
}
public void onResourceReady(Resource<?> resource) {
...
//调用重载方法
onResourceReady(resource, (R) received);
}
重载方法里面调用了target的onResourceReady方法
private void onResourceReady(Resource<?> resource, R result) {
if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,
isFirstReadyResource())) {
GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstReadyResource());
//调用target方法的onResourceReady方法
target.onResourceReady(result, animation);
}
status = Status.COMPLETE;
this.resource = resource;
notifyLoadSuccess();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "
+ (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);
}
}
由前面可知,我们的这个target是个GlideDrawableImageViewTarget对象,因此看onResourceReady方法
public class GlideDrawableImageViewTarget extends ImageViewTarget<GlideDrawable> {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
super.onResourceReady(resource, animation);
this.resource = resource;
resource.setLoopCount(maxLoopCount);
resource.start();
}
}
调用了父类的onResourceReady方法,父类会调用子类的setResource方法,因此我们看setResource方法
就是最终在我们传入的ImageView设置drawable
protected void setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
网友评论