Glide源码解读(二)

前面文章分析到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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章