(拾起.笔记)源码分析记录之Glide源码分析(一)

2018-06-14  本文已影响0人  其实小吴人挺好

写在前面

这篇文章是个人参考源码及博客编写的笔记,主要是对源码简单分析。都是个人对源码的见解记录下来,只是介绍流程,供个人参考,如有需要阅读的,建议对源码和本文进行对照分析或者打开两个界面,以免翻车。文章有点长。

开始:

分析Glide版本:compile 'com.github.bumptech.glide:glide:3.7.0'
查看源码时请对应版本,以免混乱

Glide.with(context).load(url).into(imageView);

上面就是Glide API调用最基本的的流程

点进去Glide 就会看到with方法中会有四个方法,其中的参数又Activity 、context 、fragmentActivity、application

Q1

这里使用的是Activity为参数传递进去

public static RequestManager with(Activity activity) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(activity);

}

在with方法中可以接收五种不同的参数,看下图


444.png

这里只需要对参数为activity情况下进行分析,
RequestManagerRetriever.get() 获取一个RequestManagerRetriever 对象之后,调用get(activity)方法,然后将RequestManagerRetriever

Q2 get(Activity)。

public RequestManager get(Activity activity) {

    //判断是否是后台线程,也就是是否在UI线程

    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        return get(activity.getApplicationContext());
    } else {
        assertNotDestroyed(activity);
        android.app.FragmentManager fm = activity.getFragmentManager();
        return fragmentGet(activity, fm);

    }

}

前面的判断是在判断是否是后台线程,否则为UI线程,如果后台线程,就传入一个application上下文,然后进入到else方法中。先确保它还没销毁(assertNotDestroyed),再调用activity.getFragmentManager()通过activity获取一个Fragment的管理器,然后做为参数传入到fragmentGet(activity, fm) 方法中。

Q3

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {

    RequestManagerFragment current = getRequestManagerFragment(fm);

    RequestManager requestManager = current.getRequestManager();

    if (requestManager == null) {

        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());

        current.setRequestManager(requestManager);

    }

    return requestManager;

}

RequestManagerFragment 是继承于fragment,也就是说RequestManagerFragment 其实就是一个

fragment,自定义该类的其实就是在里面创建一个ActivityFragmentLifecycle,并将它的生命周期和

fragment相关联起来;

getRequestManagerFragment(fm)就是创建一个RequestManagerFragment

Q4

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {

    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);

    if (current == null) {

        current = pendingRequestManagerFragments.get(fm);

        if (current == null) {

            current = new RequestManagerFragment();

            pendingRequestManagerFragments.put(fm, current);

            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();

            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();

        }

    }

    return current;

}

在创建RequestManagerFragment 的时候,它是通过findFragmentByTag来获取,如果没有就又从

保存的队列里面获取,再没有就new出一个,然后保存入Map中,在添加到FragmentManager中,然后发送一条handle消息,再将RequestManagerFragment返回

我们回到Q3中

在getRequestManagerFragment的时候,如果不是new出来一个新的RequestManager 就不会为空,否则它也会去创建一个RequestManager 并将生命周期的监听和树节点,并将RequestManager 设置到getRequestManagerFragment中去再将RequestManager

这里with的一系列源码已经解析完成了。其主要的目的就是创建一个fragment并且监听绑定它的生命周期变换,以免在glide在图片请求的时候,做一系列的停止等操作。

with方法就是通过监听fragment生命周期对图片进行操作,比如说暂停加载等

接下来就load()

因为with的时候返回的是RequestManager ,所以load就是RequestManager 的方法

在Request有多个load方法

111.png

其中包括byte数组、file、uri等等,说明Glide 可以接收多种类型的请求,这里我们对load(String)进行分析

Q5

public DrawableTypeRequest<String> load(String string) {

    return (DrawableTypeRequest<String>) fromString().load(string);

}

这个方法会返回一个DrawableTypeRequest类型,并指定它的泛型是String,然后调用

fromString() 再调用load(String)

进去看看fromString

Q6

public DrawableTypeRequest<String> fromString() {

    return loadGeneric(String.class);

}

private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {

    ModelLoader<T, InputStream> streamModelLoader= Glide.buildStreamModelLoader(modelClass, context);

    ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =

    Glide.buildFileDescriptorModelLoader(modelClass, context);

    ....

    return optionsApplier.apply(new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,glide, requestTracker, lifecycle, optionsApplier));

}

这个方法很短,调用Glide.buildStreamModelLoader(modelClass, context) 和 Glide.buildFileDescriptorModelLoader(modelClass, context)都返回一个ModelLoader对象。这里我们只要知道 ModelLoader 接口是加载图片的就好,因为里面过于复杂,不做过多介绍。他会根据你传入的参数类型返回相应的对象,我们在fromString方法传入的是String.class,所以这里会返回StreamStringLoader。最后一行会new 一个 DrawableTypeRequest 将 modelClass,StreamStringLoader等参数传进去,并将其返回。

Q7

222.png

进入到该类,其他的我们先不要注意,你会发现该类中有asGif(),asBitmap(),这个就是我们在强制指定加载静态图片和动态图片,看看它的方法

Q8

public BitmapTypeRequest<ModelType> asBitmap() {

    return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,fileDescriptorModelLoader, optionsApplier));

}

public GifTypeRequest<ModelType> asGif() {

    return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));

}

源码看出,如果指定了asBitmap()或者asGif(),默认的会使用DrawableTypeRequest,使用fromString()就返回一个DrawableTypeRequest,再来Q5 中的load(Stirng),点进去直接跳到DrawableTypeRequest的父类DrawableRequestBuilder。

Q9

@Override

public DrawableRequestBuilder<ModelType> load(ModelType model) {

    super.load(model);

    return this;

}

public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {

    this.model = model;

    isModelSet = true;

    return this;

}

只是简单的赋值并返回this,看看它的全部方法

333.png

回发现,我们在调用api的时候,使用的方法大都在这个类中。致此load已经分析好了

看一下into,这个方法较为复杂,这里只分析主线,对于分岔路可以自行去分析。

在load分析的DrawableRequestBuilder类方法的截图中,你会看到一个into(),这个就是into的入口

进去看看:

Q10

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));
}

前面一些代码先不用管,我们先注意一下最后一行代码,into(glide.buildImageViewTarget(view, transcodeClass)); 在into当中调用glide.buildImageViewTarget(view, transcodeClass),老规矩,进去看看

Q11

<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {

    return imageViewTargetFactory.buildTarget(imageView, transcodedClass);

}

紧接的是调用一个buildTarget

Q12

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)");

    }

}

这里会根据class来判断要创建哪个对象,这里我们只需要知道会返回一个 GlideDrawableImageViewTarget对象,因为如果要分析其class的话,还要需要很大的功夫,这里我们只关心主线,返回GlideDrawableImageViewTarget,我们回到Q10中的最后一行代码,into(GlideDrawableImageViewTarget),

Q13

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())");

    }

    Request previous = target.getRequest();

    if (previous != null) {

        previous.clear();

        requestTracker.removeRequest(previous);

        previous.recycle();

    }

    Request request = buildRequest(target);

    target.setRequest(request);

    lifecycle.addListener(target);

    requestTracker.runRequest(request);

    return target;

}

其中target.getRequest()是获取当前的taget是否有请求,如果存在就将它清空回收,然后在重新创建一个Request请求对象,也就是调用huildRequest(target),

我们看看 buildRequest(target)方法,会返回一个Request类型,

Q14

private Request buildRequest(Target<TranscodeType> target) {

    if (priority == null) {

        priority = Priority.NORMAL;

    }

    return buildRequestRecursive(target, null);

}

再调用buildRequestRecursive 把 GlideDrawableImageViewTarget 和 null 丢进去

Q15

private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {

    .....

    } else {

        // Base case: no thumbnail.

        return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);

    }

}

主要看最后一行 obtainRequest(target, sizeMultiplier, priority, parentCoordinator);

Q16

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,

    fallbackDrawable,

    fallbackResource,

    requestListener,

    requestCoordinator,

    glide.getEngine(),

    transformation,

    transcodeClass,

    isCacheable,

    animationFactory,

    overrideWidth,

    overrideHeight,

    diskCacheStrategy);

}

紧接的会将一些乱七八糟的参数传入到 GenericRequest.obtain(..)方法中

Q17

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(loadProvider,

    model,

    signature,

    context,

    priority,

    target,

    sizeMultiplier,

    placeholderDrawable,

    placeholderResourceId,

    errorDrawable,

    errorResourceId,

    fallbackDrawable,

    fallbackResourceId,

    requestListener,

    requestCoordinator,

    engine,

    transformation,

    transcodeClass,

    isMemoryCacheable,

    animationFactory,

    overrideWidth,

    overrideHeight,

    diskCacheStrategy);

    return request;

}

这里会调用request = new GenericRequest<A, T, Z, R>() 创建出一个GenericRequest对象,并将这些乱七八糟的参数传进来,并返回GenericRequest,其中很多的参数我们都是比较熟悉的,像什么placeholderId、errorPlaceholder、diskCacheStrategy等等,这里可以看出,刚才在GenericRequestBuilder中设置的参数都会封装到此处来,也就是Glide的API,所以在Q13中的buildRequest(target); 返回来的Request对象,其实就是GenericRequest,GenericRequest里面封装这api中的属性值。

接下来我们回到Q13中,看看这个方法 requestTracker.runRequest(request) ,调用runRequest将GenericRequest传递过去,来看看runRequest方法

Q18

public void runRequest(Request request) {

    requests.add(request);

    if (!isPaused) {

        request.begin();

    } else {

        pendingRequests.add(request);

    }

}

这里判断Glide状态是否为停止的状态,然后调用GenericRequest的begin() 方法,否则将Request添加到待执行队列,所以我们进去看看GenericRequest的begin方法

Q19

@Override

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));

    }

}

我们先看看onException(null) ,先判断model是否为空,mode就是在Q9 中 load传过来的String,也就是uri,也就是说uri为空的时候,就会调用onException方法,进去看看

Q20

@Override

public void onException(Exception e) {

    if (Log.isLoggable(TAG, Log.DEBUG)) {

        Log.d(TAG, "load failed", e);

    }

    status = Status.FAILED;

    //TODO: what if this is a thumbnail request?

    if (requestListener == null || !requestListener.onException(e, model, target, isFirstReadyResource())) {

        setErrorPlaceholder(e);

    }

}

经过一系列的判断后,会调用setErrorPlaceholder(e),看名字就知道,他就是用来设置占位符的,也就是错误图片

Q21

private void setErrorPlaceholder(Exception e) {

    if (!canNotifyStatusChanged()) {

        return;

    }

    Drawable error = model == null ? getFallbackDrawable() : null;

    if (error == null) {

        error = getErrorDrawable();

    }

    if (error == null) {

        error = getPlaceholderDrawable();

    }

    target.onLoadFailed(e, error);

}

这里判断error是否为空之后,就会获取一个error图片,还是没有的话再获取一个placeholder图片

然后调用target.onLoadFailed(e, error) 这个tagat就是Q11 和Q12中的GlideDrawableImageViewTarget ,进去之后onLoadFailed()是在它父类ImageViewTarget中

Q22

@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {

    view.setImageDrawable(errorDrawable);

}

只是将Drawable 设置进ImageView中去。onExption()方法就是这样,所以我们接下来回到Q19 对下面就行分析,

Q23

@Override
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));

    }

}

这里会调用到onSizeReady() 方法,这个宽高是自定义的宽高,是通过一系列的运算之后得到的宽高,点击进去看看这个方法,

Q24

@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("Failed to load model: \'" + model + "\'"));

        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;

    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));

    }

}

这时会看到一个loadProvider.getModeLoader()方法,在同getModeLoader之后获取到一个ModeLoader对象在调用它的getResource(model,width,height);方法获取到一个DataFetcher对象,这里先去了解一下loadProvider.getModeLoader()的方法,这个loadProvider其实就是分析load()方法的时候进行初始化的,我们回到在Q6 中在loadGeneric的时候,会创建出一个DrawableTypeRequest,在构造方法的时候,会调用super方法,super方法的第三个参数当中需要传入一个LoadProvider 对象,然后就会调用buildProvider加载出一个LoadProvider对象,想看看这个类

Q25

public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {

private final ModelLoader<ModelType, InputStream> streamModelLoader;

private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;

private final RequestManager.OptionsApplier optionsApplier;

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);

}

    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;

    }

    public BitmapTypeRequest<ModelType> asBitmap() {

        return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,

        fileDescriptorModelLoader, optionsApplier));

    }

    public GifTypeRequest<ModelType> asGif() {

        return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
    }

}

先看看 transcoder = glide.buildTranscoder(resourceClass, transcodedClass),这里你只要知道会返回一个ResourceTranscoder的子类GifBitmapWrapperDrawableTranscoder对象,它是用于对图片进行转码,紧接的就是glide.buildDataProvider(ImageVideoWrapper.class, resourceClass) 构建一个DataLoadProvider,这里你也需要只知道它是创建一个ImageVideoGifDrawableLoadProvider

对象,再接的就是new ImageVideoModelLoader 将在Q6 中构建的ModelLoade封装进去,最后就是通过 new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider); 将ImageVideoModelLoader,GifBitmapWrapperDrawableTranscoder,ImageVideoGifDrawableLoadProvider封装进去,所以在Q24中的loadProvider其实就是FixedLoadProvider,也就是说loadProvider.getModelLoader()获取的就是封装进去的ImageVideoModelLoader,接下来回到Q24中,会通过ImagVideoModelLoader对象调用这个modelLoader.getResourceFetcher(model, width, height)方法获取到一个DataFetcher对象,进去看看ImagVideoModelLoader这个类

Q26

public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> {

    private static final String TAG = "IVML";

    private final ModelLoader<A, InputStream> streamLoader;

    private final ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader;

    public ImageVideoModelLoader(ModelLoader<A, InputStream> streamLoader,

    ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader) {

        if (streamLoader == null && fileDescriptorLoader == null) {

            throw new NullPointerException("At least one of streamLoader and fileDescriptorLoader must be non null");

        }

        this.streamLoader = streamLoader;

        this.fileDescriptorLoader = fileDescriptorLoader;

    }

    @Override

    public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {

        DataFetcher<InputStream> streamFetcher = null;

        if (streamLoader != null) {

            streamFetcher = streamLoader.getResourceFetcher(model, width, height);

        }

            DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;

        if (fileDescriptorLoader != null) {

            fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height);

        }

        if (streamFetcher != null || fileDescriptorFetcher != null) {

            return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);

        } else {

            return null;

        }

    }

    static class ImageVideoFetcher implements DataFetcher<ImageVideoWrapper> {

        private final DataFetcher<InputStream> streamFetcher;

        private final DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher;

        public ImageVideoFetcher(DataFetcher<InputStream> streamFetcher,

        DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher) {

            this.streamFetcher = streamFetcher;

            this.fileDescriptorFetcher = fileDescriptorFetcher;

        }
    }


    @SuppressWarnings("resource")

    // @see ModelLoader.loadData

    @Override

    public ImageVideoWrapper loadData(Priority priority) throws Exception {

        InputStream is = null;

        if (streamFetcher != null) {

            try {

                is = streamFetcher.loadData(priority);

            } catch (Exception e) {

                if (Log.isLoggable(TAG, Log.VERBOSE)) {

                    Log.v(TAG, "Exception fetching input stream, trying ParcelFileDescriptor", e);

                    }

                if (fileDescriptorFetcher == null) {

                    throw e;

                }

            }

        }

        ParcelFileDescriptor fileDescriptor = null;

        if (fileDescriptorFetcher != null) {

            try {

                fileDescriptor = fileDescriptorFetcher.loadData(priority);

            } catch (Exception e) {

                if (Log.isLoggable(TAG, Log.VERBOSE)) {

                    Log.v(TAG, "Exception fetching ParcelFileDescriptor", e);

                }

                if (is == null) {

                    throw e;

                }

            }

        }

        return new ImageVideoWrapper(is, fileDescriptor);

    }

}

看看getResourceFetcher方法中,获取一个streamFetcher ,streamLoader就是我们在loadGeneric()方法中创建的StreamStringLoader,调用他的getResourceFetcher就是得到一个HttpUrlFetcher,后面就是new ImageVideoFetcher 将HttpUrlFetcher和StreamStringLoader传进去,所以,我们在Q24得到的DataFetcher其实就是这个ImageVideoFetcher ,回到Q24中,接下来就是调用 engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,priority, isMemoryCacheable, diskCacheStrategy, this) 其中dataFetcher

就是我们的ImageVideoFetcher,loadProvider就是 Q24中的FixedLoadProvider,transcoder就是FixedLoadProvider中的GifBitmapWrapperDrawableTranscoder,其中还包括是否开启内存缓存,硬盘缓存策略,还有一个this,这个this就是ResourceCallback接口,这个接口GenericRequest已经实现,然后就是engine中的load方法,

Q26.1

public <T, Z, R> LoadStatus load(....) {

.....

    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);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {

        logWithTimeAndKey("Started new load", startTime, key);

    }

    return new LoadStatus(cb, engineJob);

}

看到一个engineJobFactory.build(...)其实就是创建一个EngineJob 对象,它是用来开启线程的,为后面的异步加载图片做准备。然后就是DecodeJob对象,是用来给是图片进行解码的。

还有一个EngineRunnable,看名字就知道的,它是一个Runnable的子类,任何将DecodeJob,EngineJob 传进去,所以看看它的run方法,

Q27

@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);

    }

}

这个run方法一旦运行,就说明它是在子线程中运行了,其中里面包括一个decode()方法

Q28

private Resource<?> decode() throws Exception {

    if (isDecodingFromCache()) {

        return decodeFromCache();

    } else {

        return decodeFromSource();

    }

}

这里会判断它是否是从缓存中去解码图片就会调用decodeFromCache,否则就调用decodeFromSource,我们先看看decodeFromSource方法,

Q29

private Resource<?> decodeFromSource() throws Exception {

    return decodeJob.decodeFromSource();

}

接着他会调用DecodeJob对象中的decodeFromSource方法,

Q30

public Resource<Z> decodeFromSource() throws Exception {

    Resource<T> decoded = decodeSource();

    return transformEncodeAndTranscode(decoded);

}

接着就是再调用decodeSource() 获取一个Resource对象,再调用transformEncodeAndTranscode()将Resource对象传进去处理,再返回一个Resource对象。先进入到decodeSource中,

Q31

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;

}

注意到一个方法,fetcher.loadData(priority),返回一个A,这个fercher就是在Q24、25、26中通过

ImagVideoModelLoader得到一个ImageVideoFetcher对象,再来调用他的loadData方法,所以进去瞧一瞧

Q32

@Override

public ImageVideoWrapper loadData(Priority priority) throws Exception {

    InputStream is = null;

    if (streamFetcher != null) {

        try {

            is = streamFetcher.loadData(priority);

        } catch (Exception e) {

            if (Log.isLoggable(TAG, Log.VERBOSE)) {

                Log.v(TAG, "Exception fetching input stream, trying ParcelFileDescriptor", e);

            }

            if (fileDescriptorFetcher == null) {

                throw e;

            }

        }

    }

    ParcelFileDescriptor fileDescriptor = null;

    if (fileDescriptorFetcher != null) {

        try {

            fileDescriptor = fileDescriptorFetcher.loadData(priority);

        } catch (Exception e) {

            if (Log.isLoggable(TAG, Log.VERBOSE)) {

                Log.v(TAG, "Exception fetching ParcelFileDescriptor", e);

            }

            if (is == null) {

                throw e;

            }

        }

    }

    return new ImageVideoWrapper(is, fileDescriptor);

}

就在这里,InputStream is = streamFetcher.loadData(priority); 这货返回一个InputStream 对象,也就是说streamFetcher.loadData(priority)就是请求数据返回来的图片流,这个streamFetcher就是在Q26 中new ImageVideoFetcher时传的HttpUrlFetcher和StreamStringLoader中的HttpUrlFetcher,所以这个streamFetcher.loadData(priority)就是调用HttpUrlFetcher中的loadData方法,看看呗

Q33

@Override
public InputStream loadData(Priority priority) throws Exception {

    return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());

}

private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)throws IOException {

    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);

        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {

        urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());

        }

    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) {

        return getStreamForSuccessfulRequest(urlConnection);

    } 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, headers);

    } else {

        if (statusCode == -1) {

            throw new IOException("Unable to retrieve response code from HttpUrlConnection.");

        }

        throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());

    }

}

这些就是网络请求,返回一个InputStream 对象,回到Q32中,最后一行的new ImageVideoWrapper(is, fileDescriptor),返回一个ImageVideoWrapper对象,然后将InputStream 封装进去,所以在Q31中的A 类型就是ImageVideoWrapper对象,Q31 DecodeJob.decodeSource中的final A data = fetcher.loadData(priority)分析完了,在回头看看Q31中,看这一行,decoded = decodeFromSourceData(data),将ImageVideoWrapper对象传进去

Q34

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;

}

注意这个 decoded = loadProvider.getSourceDecoder().decode(data, width, height);这个方法,loadProvider就是FixedLoadProvider,在Q25中有解释,调用他的getSourceDecoder()获取到他在构造的时候传进去的ImageVideoGifDrawableLoadProvider对象,在调用它在构造方法中创建的GifBitmapWrapperResourceDecoder对象,再调用GifBitmapWrapperResourceDecoder的decode方法,

Q35

@SuppressWarnings("resource")

// @see ResourceDecoder.decode

@Override
public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException {

    ByteArrayPool pool = ByteArrayPool.get();

    byte[] tempBytes = pool.getBytes();

    GifBitmapWrapper wrapper = null;

    try {

        wrapper = decode(source, width, height, tempBytes);

    } finally {

        pool.releaseBytes(tempBytes);

    }

    return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null;

}

再调用它的decode重载方法

Q36

private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {

    final GifBitmapWrapper result;

    if (source.getStream() != null) {

        result = decodeStream(source, width, height, bytes);

    } else {

        result = decodeBitmapWrapper(source, width, height);

    }

    return result;

}

判断source是否为空,sourcek就是ImageVideoWrapper,也就是刚才的A类型,传入到decodeFromSourceData(data)方法,而这个ImageVideoWrapper是持有InputStream对象的,是有这里不等于空,则调用decodeStream,

Q37

private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)throws IOException {

    InputStream bis = streamFactory.build(source.getStream(), bytes);

    bis.mark(MARK_LIMIT_BYTES);

    ImageHeaderParser.ImageType type = parser.parse(bis);

    bis.reset();

    GifBitmapWrapper result = null;

    if (type == ImageHeaderParser.ImageType.GIF) {

        result = decodeGifWrapper(bis, width, height);

    }

    // Decoding the gif may fail even if the type matches.

    if (result == null) {

        // We can only reset the buffered InputStream, so to start from the beginning of the stream, we need to

        // pass in a new source containing the buffered stream rather than the original stream.

        ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());

        result = decodeBitmapWrapper(forBitmapDecoder, width, height);

    }

    return result;

}

这里先判断是否为GIF,是就调用decodeGifWrapper(bis, width, height),否则会创建一个ImageVideoWrapper 对象,调用decodeBitmapWrapper(forBitmapDecoder, width, height)传进去,所以加载普通图片就先进入到decodeBitmapWrapper方法中

Q38

private GifBitmapWrapper decodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException {

    GifBitmapWrapper result = null;

    Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode, width, height);

    if (bitmapResource != null) {

        result = new GifBitmapWrapper(bitmapResource, null);

    }

    return result;

}

通过调用 bitmapDecoder.decode(toDecode, width, height) 返回一个Resource对象,再将它封装到GifBitmapWrapper中,这个ditmapDecoder我们只要知道是一个 ImageVideoBitmapDecoder对象,我们只要往主线走,我们看一下他的方法,

Q39

@Override

public Resource<Bitmap> decode(ImageVideoWrapper source, int width, int height) throws IOException {

    Resource<Bitmap> result = null;

    InputStream is = source.getStream();

    if (is != null) {

        try {

            result = streamDecoder.decode(is, width, height);

        } catch (IOException e) {

            if (Log.isLoggable(TAG, Log.VERBOSE)) {

                Log.v(TAG, "Failed to load image from stream, trying FileDescriptor", e);

            }

        }

    }

    if (result == null) {

        ParcelFileDescriptor fileDescriptor = source.getFileDescriptor();

        if (fileDescriptor != null) {

            result = fileDescriptorDecoder.decode(fileDescriptor, width, height);

        }

    }

    return result;

}

在获取到ImageVideoWrapper 中的InputStream,之后再调用streamDecoder.decode(is, width, height);获取一个Resource<Bitmap> 泛型为Bitmap,这个streamDecoder只需要知道他是StreamBitmapDecoder对象,再来看看他的decode方法,

Q40

@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);

}

然后。。它又去调用 downsampler.decode(source, bitmapPool, width, height, decodeFormat) 返回一个Bitmap对象,再封装到Resource中,downsampler就是Downsampler,里面主要是将InputStream 处理得到一个Bitmap对象,再是用BitmapResource将其封装,

Q41

public static BitmapResource obtain(Bitmap bitmap, BitmapPool bitmapPool) {
    if(bitmap == null) { 
        return null;
    }else{
        return new BitmapResource(bitmap, bitmapPool);
    }
 }

是的,就是new 一个BitmapResource,所以得出,在Q38中streamDecoder.decode(is, width, height)方法中获取的就是一个BitmapResourced对象,然后在将BitmapResource对象封装到GifBitmapWrapper方法中,然后返回一步一步向上返回GifBitmapWrapper,Q38 到 Q37 到Q36 到Q35 ,那回到 Q35

@Override
public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException {

    ByteArrayPool pool = ByteArrayPool.get();

    byte[] tempBytes = pool.getBytes();

    GifBitmapWrapper wrapper = null;

    try {

        wrapper = decode(source, width, height, tempBytes);

        } finally {

        pool.releaseBytes(tempBytes);

    }

    return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null;

}

最后一行又创建了一次GifBitmapWrapperResource对GifBitmapWrapper进行封装,然后将GifBitmapWrapperResource返回到Q34 ,GifBitmapWrapperResource是继承自Resource,所以将这个GifBitmapWrapperResource返回到Q34,再到Q31,然后在到Q30

到Q30 看看,我们刚刚就是分析的decodeSource,返回一个GifBitmapWrapperResource(wrapper) ,将GifBitmapWrapperResource 传入到transformEncodeAndTranscode方法中

public Resource<Z> decodeFromSource() throws Exception {

    Resource<T> decoded = decodeSource();

    return transformEncodeAndTranscode(decoded);

}

transformEncodeAndTranscode方法的返回值也是一个Resource对象,不过他的泛型是不一样的,一个Z 一个T,先看看这个方法吧

Q42

private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {

    long startTime = LogTime.getLogTime();

    Resource<T> transformed = transform(decoded);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {

        logWithTimeAndKey("Transformed resource from source", startTime);

    }

    writeTransformedToCache(transformed);

    startTime = LogTime.getLogTime();

    Resource<Z> result = transcode(transformed);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {

        logWithTimeAndKey("Transcoded transformed from source", startTime);

    }

    return result;

}

注意到 Resource<Z> result = transcode(transformed) 这段代码,又调用trancode(transformed)来看看

Q43

private Resource<Z> transcode(Resource<T> transformed) {

    if (transformed == null) {

        return null;

    }

    return transcoder.transcode(transformed);

}

transcoder是在DecodeJob初始化的时候传来,初始化的时候是在Engine.load(Q26) 的方法中,而调用Engine.load是在GenericRequest的onSizeReady(Q24)中,通过loadProvider.getTranscoder()获取出来的

而这个loadProvider就是Q25中创建出来的 FixedLoadProvider并传入3个参数,而他获取getTranscoder()就是Q25中初始化传入的GifBitmapWrapperDrawableTranscoder,我们看一下GifBitmapWrapperDrawableTranscoder中的transcode方法

Q44

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;

}

可以看到,它是先从GifBitmapWrapperResource中取出GifBitmapWrapper,再从GifBitmapWrapper中取出BitmapResource (Q38,39,40,41 有解释了),然后判断是否为空之后调用bitmapDrawableResourceTranscoder.transcode(bitmapResource),否则调用gifBitmap.getGifResource()方法加载一个gif图片。跟GifBitmapWrapperDrawableTranscoder一样,只需要知道这个bitmapDrawableResourceTranscoder是GlideBitmapDrawableTranscoder对象就可以了,否则分析会不完。所以接下来就会调用GlideBitmapDrawableTranscoder中的transcode方法将BitmapResource 传进去。

Q45

@Override
public Resource<GlideBitmapDrawable> transcode(Resource<Bitmap> toTranscode) {

    GlideBitmapDrawable drawable = new GlideBitmapDrawable(resources, toTranscode.get());

    return new GlideBitmapDrawableResource(drawable, bitmapPool);

}

这里面又做了两个动作,new GlideBitmapDrawable对象,并获取出BitmapResource 中的Bitmap封装到里面,在返回一个GlideBitmapDrawableResource,又把GlideBitmapDrawable传进去返回,所以Q44当中返回的就是GlideBitmapDrawableResource对象,返回的就是Resource<GlideBitmapDrawable>,Q42 中的这个Z就是GlideBitmapDrawable,所以我们回到Q44当中,这个Resource<? extends GlideDrawable> result 就是GlideBitmapDrawableResource<GlideBitmapDrawable> 将它返回到Q42 再返回到 Q30中再到Q27 (跨度又点大),也就是回到EngineRunnable的run方法中。

@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() 有够深的,decode返回的就是上面分析的Resource<GlideDrawable>,最后判断是否为空之后,调用onLoadComplete传进去,

Q46

private void onLoadComplete(Resource resource) {

    manager.onResourceReady(resource);

}

这个manager就是Q26 传的EngineJob对象,看看呗

Q47

@Override
public void onResourceReady(final Resource<?> resource) {

    this.resource = resource;

    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();

}

将 Resource<?> resource赋值给成员变量之后,发送一个消息,把自己传过去。Handler 就是EngineJob中的静态内部类,在run方法运行后就一直在子线程中执行上面分析的逻辑代码,只有在这里的时候才通过handler回到子线程当中来,所以可以猜到,接下来的代码就是执行图片展示的代码。

Q48

private static class MainThreadCallback implements Handler.Callback {

    @Override
    public boolean handleMessage(Message message) {

        if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {

            EngineJob job = (EngineJob) message.obj;

            if (MSG_COMPLETE == message.what) {

                job.handleResultOnMainThread();

            } else {

                job.handleExceptionOnMainThread();

            }

            return true;

        }

        return false;

    }

}

接下来就是调用 EngineJob 中的 handleResultOnMainThread方法,

Q49

private void handleResultOnMainThread() {

......

    for (ResourceCallback cb : cbs) {

        if (!isInIgnoredCallbacks(cb)) {

            engineResource.acquire();

            cb.onResourceReady(engineResource);

        }

    }

    // Our request is complete, so we can release the resource.

    engineResource.release();

}

看到一个for循环,遍历获取cbs,cbs是一个成员变量的集合private final List<ResourceCallback> cbs = new ArrayList<ResourceCallback>(),通过遍历获取到ResourceCallback ,那么ResourceCallback 添加是在什么时候的?在EngineJob的时候还有一个add的方法,

Q50

public void addCallback(ResourceCallback cb) {

        Util.assertMainThread();

        if (hasResource) {

            cb.onResourceReady(engineResource);

        } else if (hasException) {

            cb.onException(exception);

        } else {

            cbs.add(cb);

        }

}

最后就是cbs.add 将传进来的参数添加进集合中。这个addCallback方法就在Engine.load(Q26 )中调用的,而且是作为load的参数传进来的,我们在Q24Q25的时候有分析过,在GenericRequst.onSizeReady()方法中我们调用engine.load时传入很多参数,在最后一个参数的时候会传入一个this,也就是GenericRequst的本身,也就是GenericRequst实现了ResourceCallback接口,所以EngineJob最终调用的就是GenericRequst的onResourceReady方法。

Q51

public void onResourceReady(Resource<?> resource) {

    if (resource == null) {

        onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass

        + " inside, but instead got null."));

        return;

    }

    Object received = resource.get();

    if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {

        releaseResource(resource);

        onException(new Exception("Expected to receive an object of "     + transcodeClass

            + " but instead got " + (received != null ? received.getClass() : "") + "{" + received + "}"

            + " inside Resource{" + resource + "}."

            + (received != null ? "" : " "

            + "To indicate failure return a null Resource object, "

            + "rather than a Resource object containing null data.")

            ));

        return;

    }

    if (!canSetResource()) {

        releaseResource(resource);

        // We can't set the status to complete before asking canSetResource().

        status = Status.COMPLETE;

        return;

    }

    onResourceReady(resource, (R) received);

}

先获取到resource.get() ,也就是上面分析的Q45 中的GlideBitmapDrawable, 再作为参数调用他的重载方法,

Q52

private void onResourceReady(Resource<?> resource, R result) {

    // We must call isFirstReadyResource before setting status.

    boolean isFirstResource = isFirstReadyResource();

    status = Status.COMPLETE;

    this.resource = resource;

    if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,isFirstResource)) {

        GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);

        target.onResourceReady(result, animation);

    }

    notifyLoadSuccess();

}

这里只要看到他的 target.onResourceReady(result, animation)方法,target知道,也就是前面分析(Q12)中的封装ImageView的GlideDrawableImageViewTarget对象,调用它的onResourceReady方法

Q53

public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {

    if (!resource.isAnimated()) {

        //TODO: Try to generalize this to other sizes/shapes.

        // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly

        // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.

        // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions,

        // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers

        // lots of these calls and causes significant amounts of jank.

        float viewRatio = view.getWidth() / (float) view.getHeight();

        float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();

        if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN

        && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {

            resource = new SquaringDrawable(resource, view.getWidth());

        }

    }

    super.onResourceReady(resource, animation);

    this.resource = resource;

    resource.setLoopCount(maxLoopCount);

    resource.start();

}

然后会调用父类的 super.onResourceReady(resource, animation);方法,

Q54

@Override
public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {

    if (glideAnimation == null || !glideAnimation.animate(resource, this)) {

        setResource(resource);

    }

}

protected abstract void setResource(Z resource);

父类只是调用了它的 setResource 方法,而setResource 方法是一个抽象方法,所以它会调用自己的setResource 方法,

Q55

@Override
protected void setResource(GlideDrawable resource) {

    view.setImageDrawable(resource);

}

这个view就是封装的ImageView,然后将GlideDrawable 设置进来,至此,一个图片就展示出来了。

总结:

本文只是简单的分析,供个人参考

参考:

https://blog.csdn.net/guolin_blog/article/details/53939176

上一篇下一篇

猜你喜欢

热点阅读