超详细的Glide源码解析

1. 简单使用


Glide.with(this).load(url)
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .centerCrop()
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.RESULT)
                .priority(Priority.HIGH)
                .into(mIvMn);

2. with方法

参数类型:Activity,Context,Fragment,ApplicationContext(本质上也是Context) 类型决定生命周期

2.1 with方法


with方法

public static RequestManager with(Context context) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(context);
}

public static RequestManager with(Activity activity) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(activity);
}

public static RequestManager with(FragmentActivity activity) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(activity);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(fragment);
}

public static RequestManager with(Fragment fragment) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(fragment);
}

这几个重载方法最终都是调用RequestManagerRetriever.get()方法获取RequestManagerRetriever对象,然后通过这个对象获取RequestManager对象

2.2 RequestManagerRetriever对象的get方法


public RequestManager get(Context context) {
    if (context == null) {
        throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
//判断当前线程是不是主线程 并且context是不是Application 
        //分别转化为相应的Context对象
        if (context instanceof FragmentActivity) {
            return get((FragmentActivity) context);
        } else if (context instanceof Activity) {
            return get((Activity) context);
        } else if (context instanceof ContextWrapper) {
            return get(((ContextWrapper) context).getBaseContext());
        }
    }

    return getApplicationManager(context);
}

private RequestManager getApplicationManager(Context context) {
    if (applicationManager == null) {
        synchronized (this) {
            if (applicationManager == null) {
                applicationManager = new RequestManager(context.getApplicationContext(),
                        new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
            }
        }
    }

    return applicationManager;
}


@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
    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);
    }
}

1) get方法首先会判断传入的Context的类型,如果传入的Context类型是Application或者是在子线程加载的图片,这会通过getApplicationManager方法单例形式创建一个RequestManager对象。

2) 否则会调用fragmentGet方法,传入Context对象和FragmentManager对象。

2.3 fragmentGet方法


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


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

1) 通过getRequestManagerFragment创建一个没有UI界面的fragment,通过这个fragment获取RequestManager对象。

2) 如果上面获取的对象为空,就直接创建一个RequestManager对象,传入上下文,LifecycleListener对象(这是用来监听activity生命周期的接口),还有一个不知名的对象。

3) 当前fragment绑定RequestManager对象,glide是无法知道activity生命周期的,所以这里添加了一个没有UI界面的fragment来监听Activity的生命周期,这样设计很巧妙。

4) getRequestManagerFragment方法主要是去获取fragment对象,如果对象不存在,就创建一个新的对象,同时添加到activity中,并且通过Handler发送一条消息,在handlemessage中移除当前fm对象。

2.4 RequestManagerFragment类

RequestManagerFragment类

public RequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
}

// For testing only.
@SuppressLint("ValidFragment")
RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
}

ActivityFragmentLifecycle getLifecycle() {
    return lifecycle;
}

@Override
public void onStart() {
    super.onStart();
    lifecycle.onStart();
}

@Override
public void onStop() {
    super.onStop();
    lifecycle.onStop();
}

@Override
public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
}

构造方法中创建了一个ActivityFragmentLifecycle对象,这个对象就是监听fragment生命周期的,从fragment的生命周期方法中可以很明确看出来。

2.5 ActivityFragmentLifecycle类

ActivityFragmentLifecycle类

class ActivityFragmentLifecycle implements Lifecycle {


        @Override
    public void addListener(LifecycleListener listener) {
        lifecycleListeners.add(listener);

        if (isDestroyed) {
            listener.onDestroy();
        } else if (isStarted) {
            listener.onStart();
        } else {
            listener.onStop();
        }
    }
}


public interface Lifecycle {
    void addListener(LifecycleListener listener);
}

public interface LifecycleListener {

    void onStart();

    void onStop();

    void onDestroy();
}

可以看出LifecycleListener接口才是定义监听fragment生命周期的类,上面的类都不过实现了这个接口类而已。

2.6 小结

width方法最终目的都是通过RequestManagerRetriever对象的get方法获取RequestManager对象,传入参数主要分Application类型和非Application类型

1) 如果with方法传入的是Application,会通过调用getApplicationManager()来获取一个RequestManager对象,不需要处理生命周期,因为Application对象的生命周期就是应用程序的生命周期

2) 如果with方法传入的不是Application类型,最终流程都是一样,那就是会向当前的Activity当中添加一个隐藏的Fragment,app包下的fragment会调用fragmentGet方法创建隐藏fragment,v4包下的fragment会调用supportFragmentGet方法创建fragment,都会返回RequestManager对象,创建隐藏fragment的目的是Glide需要知道加载的生命周期,可是Glide并没有办法知道Activity的生命周期,于是Glide就使用了添加隐藏Fragment的这种小技巧,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了。

3)如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理,调用getApplicationManager()来获取RequestManager对象

3. load方法

参数类型:String,File,byte[],URL,图片资源ID,Uri,我这里只看参数类型为String类型的,这些方法都会返回DrawableTypeRequest对象。

3.1 load方法

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


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);
    if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
        throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
                + " which there is a registered ModelLoader, if you are using a custom model, you must first call"
                + " Glide#register with a ModelLoaderFactory for your custom model class");
    }

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

load内部调用了fromString方法,fromString方法调用了loadGeneric方法,
loadGeneric()方法也没几行代码,这里分别调用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法来获得ModelLoader对象。
ModelLoader对象是用于加载图片的,而我们给load()方法传入不同类型的参数,这里也会得到不同的ModelLoader对象。

3.2 DrawableTypeRequest类

load方法都会返回这个DrawableTypeRequest类,这里面两个重要方法是asBitmap方法和asGif方法,asBitmap方法会创建一个BitmapTypeRequest对象,同时会返回BitmapTypeRequest类型,这个方法会将图片强制转换为静态图片,asGif方法会创建一个GifTypeRequest对象,同时会返回GifTypeRequest类型,这个方法会强制将图片转换为动态图片,如果图片本身是静态图片,则图片加载会失败。

3.3 DrawableRequestBuilder类

它是DrawableTypeRequest的父类,这里面提供了glide加载图片过程的很多方法,比如animate,centerCrop,crossFade,error,fitCenter,placeholder,skipMemoryCache,priority等等…


public class DrawableRequestBuilder<ModelType>
        extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
        implements BitmapOptions, DrawableOptions {

    DrawableRequestBuilder(Context context, Class<ModelType> modelClass,
            LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
            RequestTracker requestTracker, Lifecycle lifecycle) {
        super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
        // Default to animating.
        crossFade();
    }


    //图片的一种显示格式
    @SuppressWarnings("unchecked")
    public DrawableRequestBuilder<ModelType> centerCrop() {
        return transform(glide.getDrawableCenterCrop());
    }

    //图片的一种显示格式
    @SuppressWarnings("unchecked")
    public DrawableRequestBuilder<ModelType> fitCenter() {
        return transform(glide.getDrawableFitCenter());
    }

    //图片显示设置渐变时间
    public DrawableRequestBuilder<ModelType> crossFade(int duration) {
        super.animate(new DrawableCrossFadeFactory<GlideDrawable>(duration));
        return this;
    }

    //磁盘缓存策略
     @Override
    public DrawableRequestBuilder<ModelType> diskCacheStrategy(DiskCacheStrategy strategy) {
        super.diskCacheStrategy(strategy);
        return this;
    }

    //是否跳过内存缓存
    @Override
    public DrawableRequestBuilder<ModelType> skipMemoryCache(boolean skip) {
        super.skipMemoryCache(skip);
        return this;
    }

    //设置图片尺寸
     @Override
    public DrawableRequestBuilder<ModelType> override(int width, int height) {
        super.override(width, height);
        return this;
    }

    //设置图片加载优先级
    @Override
    public DrawableRequestBuilder<ModelType> priority(Priority priority) {
        super.priority(priority);
        return this;
    }
}

3.4 GenericRequestBuilder类:DrawableRequestBuilder的父类,这里面提供了绝大部分glide加载图片过程中的方法,它的子类都是实现了这个父类。

一些重要参数
protected final RequestTracker requestTracker;
protected final Lifecycle lifecycle; 
private int placeholderId;
   private int errorId;
private Drawable placeholderDrawable;
   private Drawable errorPlaceholder;
   private Priority priority = null;
   private boolean isCacheable = true;
private int overrideHeight = -1;
   private int overrideWidth = -1;

构造方法:

GenericRequestBuilder(LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
       Class<TranscodeType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other) {
       this(other.context, other.modelClass, loadProvider, transcodeClass, other.glide, other.requestTracker,
               other.lifecycle);
       this.model = other.model;
       this.isModelSet = other.isModelSet;
       this.signature = other.signature;
       this.diskCacheStrategy = other.diskCacheStrategy;
       this.isCacheable = other.isCacheable;
}

GenericRequestBuilder(Context context, Class<ModelType> modelClass,
        LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
        Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
    this.context = context;
    this.modelClass = modelClass;
    this.transcodeClass = transcodeClass;
    this.glide = glide;
    this.requestTracker = requestTracker;
    this.lifecycle = lifecycle;
    this.loadProvider = loadProvider != null
            ? new ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType>(loadProvider) : null;

    if (context == null) {
        throw new NullPointerException("Context can't be null");
    }
    if (modelClass != null && loadProvider == null) {
        throw new NullPointerException("LoadProvider must not be null");
    }
}
4. into方法

4.1 into方法

into(ImageView  imageView)方法:

@Override
public Target<GlideDrawable> into(ImageView view) {
    return super.into(view);
}

调用父类GenericRequestBuilder的into方法
public Target<TranscodeType> into(ImageView view) {
//断言是不是在主线程 因为ui更新操作在主线程
    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方法最终会调用into(Target target)方法返回一个target对象,通过glide.buildImageViewTarget(view, transcodeClass)创建一个target对象

4.2 buildImageViewTarget方法

<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}


@SuppressWarnings("unchecked")
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)");
    }
}

创建target对象主要分两种,如果你在使用Glide加载图片的时候调用了asBitmap()方法,那么这里就会构建出BitmapImageViewTarget对象,返回BitmapImageViewTarget对象,否则返回GlideDrawableImageViewTarget对象。

4.3 into(Target target)方法

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类用于跟踪、取消和重新启动进程中、已完成和失败请求
 //执行请求
    requestTracker.runRequest(request);

    return target;
}

@Override
public void setRequest(Request request) {
    setTag(request);
}

这里首先还是检查是不是在主线程,因为更新ui的操作必须在主线程,这里首先会通过target对象获取request对象,然后清除之前的request对象,回收request对象,然后重新构建一个新的request对象,并且给这个target设置request对象,这其实就是好比listView加载图片时候给图片设置tag,防止图片错位问题,这里requestTracker.runRequest这个方法是执行这个请求。

4.4 recycle方法

@Override
public void recycle() {
    loadProvider = null;
    model = null;
    context = null;
    target = null;
    placeholderDrawable = null;
    errorDrawable = null;
    fallbackDrawable = null;
    requestListener = null;
    requestCoordinator = null;
    transformation = null;
    animationFactory = null;
    loadedFromMemoryCache = false;
    loadStatus = null;
    REQUEST_POOL.offer(this);
}

主要是对象置空,boolean值置为false

4.5 buildRequest方法:构建request对象

private Request buildRequest(Target<TranscodeType> target) {
    图片加载默认优先级是NORMAL
       if (priority == null) {
           priority = Priority.NORMAL;
       }
       return buildRequestRecursive(target, null);
   }


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);
           // Guard against infinite recursion.
           isThumbnailBuilt = true;
           // Recursively generate thumbnail requests.
           Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
           isThumbnailBuilt = false;
           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);
       }
}

buildRequestRecursive方法前面一大部分主要是如果glide调用了override,就调用这个类的override方法,以及缩略图的处理,最终还是调用的obtainRequest方法

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方法

public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
       LoadProvider<A, T, Z, R> loadProvider,
       A model,
       Key signature,
       Context context,
       Priority priority,
       Target<R> target,
       float sizeMultiplier,
       Drawable placeholderDrawable,
       int placeholderResourceId,
       Drawable errorDrawable,
       int errorResourceId,
       Drawable fallbackDrawable,
       int fallbackResourceId,
       RequestListener<? super A, R> requestListener,
       RequestCoordinator requestCoordinator,
       Engine engine,
       Transformation<Z> transformation,
       Class<R> transcodeClass,
       boolean isMemoryCacheable,
       GlideAnimationFactory<R> animationFactory,
       int overrideWidth,
       int overrideHeight,
       DiskCacheStrategy diskCacheStrategy) {
   @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_POOL.poll() 核心代码就这一句,调用了请求池的poll方法,获取request对象,如果请求池中这个对象为空,那么就创建一个GenericRequest对象,然后调用request对象的init方法进行初始化。

4.6 runRequest方法:这个方法就是执行图片请求的方法

public void runRequest(Request request) {
       requests.add(request);
       if (!isPaused) {
           request.begin();
       } else {
           pendingRequests.add(request);
       }
}

这个方法内部的逻辑是判断是不是加载状态,如果是加载状态,就调用request.begin()方法,否则就把这个请求加入到等待执行的请求队列中去。

4.7 begin方法: 真正执行request请求的方法

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

这个方法的逻辑是如果glide调用了override方法,则调用onSizeReady方法,否则调用target.getSize(this);其实后面这个方法的内部也是会调用onSizeReady方法。
如果图片没有加载完成,并且图片不是加载失败状态,就给这个target设置默认占位图。

4.8 Target对象的getSize方法

@Override
public void getSize(SizeReadyCallback cb) {
    sizeDeterminer.getSize(cb);
}

public void getSize(SizeReadyCallback cb) {
    int currentWidth = getViewWidthOrParam();
    int currentHeight = getViewHeightOrParam();
    if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
        cb.onSizeReady(currentWidth, currentHeight);
    } else {
        if (!cbs.contains(cb)) {
            cbs.add(cb);
        }
        if (layoutListener == null) {
            final ViewTreeObserver observer = view.getViewTreeObserver();
            layoutListener = new SizeDeterminerLayoutListener(this);
            observer.addOnPreDrawListener(layoutListener);
        }
    }
}

如果图片宽高没有测量完则会执行else部分图片的测量,否则也是调用onSizeReady方法

4.9 GenericRequest的onSizeReady方法


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

几个重要的对象
获取原始数据的类
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
//
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
//图片资源转换类
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
//Engine类: 负责启动负载并管理活动和缓存的资源类
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
         priority, isMemoryCacheable, diskCacheStrategy, this);

4.10 DrawableTypeRequest类的buildProvider方法得到LoadProvider对象


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


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


public interface LoadProvider<A, T, Z, R> extends DataLoadProvider<T, Z> {


    ModelLoader<A, T> getModelLoader();

    ResourceTranscoder<Z, R> getTranscoder();
}


public interface DataLoadProvider<T, Z> {


    ResourceDecoder<File, Z> getCacheDecoder();


    ResourceDecoder<T, Z> getSourceDecoder();


    Encoder<T> getSourceEncoder();


    ResourceEncoder<Z> getEncoder();
}

上面主要是创建LoadProvider对象,LoadProvider这个类主要负责图片的编码解码。

4.11 DataFetcher类


public interface DataFetcher<T> {

    T loadData(Priority priority) throws Exception;


    void cleanup();


    String getId();


    void cancel();
}

这个类主要负责将流资源转换为glide实际加载图片需要的数据,比如byte[] ,file,uri,url等。

4.12 Engine类的load方法


public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
        DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
        Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
    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;
    }

    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);
    engineJob.start(runnable);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
}

1) 通过buildKey方法构建图片缓存key对象,参数有10多个之多,比如id,签名,图片大小,数据的编码解码等等…

2)根据key从缓存中去获取缓存图片数据loadFromCache(key, isMemoryCacheable);

3)如果缓存不为空,则会调用 cb.onResourceReady(cached)方法,加载缓存数据

4)如果上面获取的缓存还是为空,则调用下面的方法继续去获取缓存数据loadFromActiveResources(key, isMemoryCacheable);

5)如果缓存不为空,也会调用cb.onResourceReady(active)方法去加载缓存数据。

6)否则会通过EngineJob这个Runnable类去加载图片。

4.13 EngineRunnable类

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

private void onLoadComplete(Resource resource) {
        manager.onResourceReady(resource);
}

@Override
  public void onResourceReady(final Resource<?> resource) {
      this.resource = resource;
      MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
  }

private void handleResultOnMainThread() {
      if (isCancelled) {
          resource.recycle();
          return;
      } else if (cbs.isEmpty()) {
          throw new IllegalStateException("Received a resource without any callbacks to notify");
      }
      engineResource = engineResourceFactory.build(resource, isCacheable);
      hasResource = true;

      engineResource.acquire();
      listener.onEngineJobComplete(key, engineResource);

      for (ResourceCallback cb : cbs) {
          if (!isInIgnoredCallbacks(cb)) {
              engineResource.acquire();
              cb.onResourceReady(engineResource);
          }
      }
      // Our request is complete, so we can release the resource.
      engineResource.release();
}


@Override
  public void onException(final Exception e) {
      this.exception = e;
      MAIN_THREAD_HANDLER.obtainMessage(MSG_EXCEPTION, this).sendToTarget();
  }

private void handleExceptionOnMainThread() {
      if (isCancelled) {
          return;
      } else if (cbs.isEmpty()) {
          throw new IllegalStateException("Received an exception without any callbacks to notify");
      }
      hasException = true;

      listener.onEngineJobComplete(key, null);

      for (ResourceCallback cb : cbs) {
          if (!isInIgnoredCallbacks(cb)) {
              cb.onException(exception);
          }
      }
}

run方法首先是去解码图片,然后判断有没有图片加载有没有取消,如果用户取消了加载,则回收资源,return,否则如果解码得到的Resource不为空则调用onLoadComplete加载完成的方法,加载完成通过Handler发送一个消息,更新UI,最终会调用EngineJob的handleResultOnMainThread方法,否则调用加载失败的方法,调用onException方法,也是通过Handler发送一个消息,更新UI,最终会调用handleExceptionOnMainThread方法

5. 图片的内存缓存

5.1 生成缓存key


public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
        DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
        Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
    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());

}

fetcher.getId()方法获得了一个id字符串,这个字符串也就是我们要加载的图片的唯一标识,比如说如果是一张网络上的图片的话,那么这个id就是这张图片的url地址。

EngineKeyl类主要重写了equal()和hashCode()方法。

Glide内存缓存的实现自然也是使用的LruCache算法。不过除了LruCache算法之外,Glide还结合了一种弱引用的机制,共同完成了内存缓存功能。

5.2 ModelLoader对象

我们当时分析到了在loadGeneric()方法中会调用Glide.buildStreamModelLoader()方法来获取一个ModelLoader对象


public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
    return buildModelLoader(modelClass, InputStream.class, context);
}

//构建ModelLoader对象
 public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
        Context context) {
     if (modelClass == null) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Unable to load null model, setting placeholder only");
        }
        return null;
    }
    return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
}

//Glide的静态方法,用于返回Glide对象
public static Glide get(Context context) {
    if (glide == null) {
        synchronized (Glide.class) {
            if (glide == null) {
                Context applicationContext = context.getApplicationContext();
                List<GlideModule> modules = new ManifestParser(applicationContext).parse();

                GlideBuilder builder = new GlideBuilder(applicationContext);
                for (GlideModule module : modules) {
                    module.applyOptions(applicationContext, builder);
                }
                glide = builder.createGlide();
                for (GlideModule module : modules) {
                    module.registerComponents(applicationContext, glide);
                }
            }
        }
    }

    return glide;
}

//创建并返回一个Glide对象
Glide createGlide() {
    if (sourceService == null) {
        final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());
        sourceService = new FifoPriorityThreadPoolExecutor(cores);
    }
    if (diskCacheService == null) {
        diskCacheService = new FifoPriorityThreadPoolExecutor(1);
    }

    MemorySizeCalculator calculator = new MemorySizeCalculator(context);
    if (bitmapPool == null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            int size = calculator.getBitmapPoolSize();
            bitmapPool = new LruBitmapPool(size);
        } else {
            bitmapPool = new BitmapPoolAdapter();
        }
    }

    if (memoryCache == null) {
        memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());
    }

    if (diskCacheFactory == null) {
        diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }

    if (engine == null) {
        engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService);
    }

    if (decodeFormat == null) {
        decodeFormat = DecodeFormat.DEFAULT;
    }

    return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
}

你会发现这里new出了一个LruResourceCache,并把它赋值到了memoryCache这个对象上面。你没有猜错,这个就是Glide实现内存缓存所使用的LruCache对象了。

5.3 内存缓存读取

实现内存缓存的读取其实还是在Engine类的load方法,源码看下:

public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
        DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
        Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
    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;
    }

    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);
    engineJob.start(runnable);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
}

1) 通过buildKey方法构建图片缓存key对象,参数有10多个之多,比如id,签名,图片大小,数据的编码解码等等…

2)根据key从缓存中去获取缓存图片数据 这个使用的是Lrucache实现的loadFromCache(key, isMemoryCacheable);

3)如果缓存不为空,则会调用cb.onResourceReady(cached)方法,加载缓存数据

4)如果上面获取的缓存还是为空,则调用下面的方法继续去获取正在加载的图片数loadFromActiveResources(key,isMemoryCacheable);这个是使用弱引用实现的。

5)如果缓存不为空,也还是调用cb.onResourceReady(active)方法去加载缓存数据。

6)否则会通过EngineJob这个Runnable类去加载图片。

5.3.1 loadFromCache和loadFromActiveResources方法


loadFromCache方法
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) {
        result = (EngineResource) cached;
    } else {
        result = new EngineResource(cached, true /*isCacheable*/);
    }
    return result;
}

loadFromActiveResources方法
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;
}

1) loadFromCache()方法是通过 getEngineResourceFromCache()方法来获取缓存。在这个方法中,会使用缓存Key来从cache当中取值,而这里的cache对象就是在构建Glide对象时创建的LruResourceCache,那么说明这里其实使用的就是LruCache算法了。

2)当我们从LruResourceCache中获取到缓存图片之后会将它从缓存中移除,然后将这个缓存图片存储到activeResources当中。activeResources就是一个弱引用的HashMap,用来缓存正在使用中的图片,我们可以看到,loadFromActiveResources()方法就是从activeResources这个HashMap当中取值的。使用activeResources来缓存正在使用中的图片,可以保护这些图片不会被LruCache算法回收掉,概括一下来说,就是如果能从内存缓存当中读取到要加载的图片,那么就直接进行回调,如果读取不到的话,才会开启线程执行后面的图片加载逻辑。

5.4 内存缓存的写入操作


@Override
public void onResourceReady(final Resource<?> resource) {
    this.resource = resource;
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}

private void handleResultOnMainThread() {
    if (isCancelled) {
        resource.recycle();
        return;
    } else if (cbs.isEmpty()) {
        throw new IllegalStateException("Received a resource without any callbacks to notify");
    }
    engineResource = engineResourceFactory.build(resource, isCacheable);
    hasResource = true;

    // Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
    // synchronously released by one of the callbacks.
    engineResource.acquire();
    listener.onEngineJobComplete(key, engineResource);

    for (ResourceCallback cb : cbs) {
        if (!isInIgnoredCallbacks(cb)) {
            engineResource.acquire();
            cb.onResourceReady(engineResource);
        }
    }
    // Our request is complete, so we can release the resource.
    engineResource.release();
}

static class EngineResourceFactory {
    public <R> EngineResource<R> build(Resource<R> resource, boolean isMemoryCacheable) {
        return new EngineResource<R>(resource, isMemoryCacheable);
    }
}

这里通过EngineResourceFactory构建出了一个包含图片资源的EngineResource对象,然后通过 listener.onEngineJobComplete(key, engineResource);这个代码将这个对象回调到Engine的onEngineJobComplete()方法当中


 @SuppressWarnings("unchecked")
@Override
public void onEngineJobComplete(Key key, EngineResource<?> resource) {
    Util.assertMainThread();
    if (resource != null) {
        resource.setResourceListener(key, this);

        if (resource.isCacheable()) {
            activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
        }
    }
    jobs.remove(key);
}

回调过来的EngineResource被put到了activeResources当中,也就是在这里写入的缓存,不过这只是弱引用缓存,还有另外一种LruCache缓存是在哪里写入的呢?这就要介绍一下EngineResource中的一个引用机制了,观察刚才的handleResultOnMainThread()方法,分别有调用EngineResource的acquire()方法,和调用它的release()方法。其实,EngineResource是用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1


void acquire() {
    if (isRecycled) {
        throw new IllegalStateException("Cannot acquire a recycled resource");
    }
    if (!Looper.getMainLooper().equals(Looper.myLooper())) {
        throw new IllegalThreadStateException("Must call acquire on the main thread");
    }
    ++acquired;
}

void release() {
    if (acquired <= 0) {
        throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
    }
    if (!Looper.getMainLooper().equals(Looper.myLooper())) {
        throw new IllegalThreadStateException("Must call release on the main thread");
    }
    if (--acquired == 0) {
        listener.onResourceReleased(key, this);
    }
}

当acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中。而经过release()之后,如果acquired变量等于0了,说明图片已经不再被使用了,那么就会调用listener的onResourceReleased()方法来释放资源,这个listener就是Engine对象

@Override
public void onResourceReleased(Key cacheKey, EngineResource resource) {
    Util.assertMainThread();
    activeResources.remove(cacheKey);
    if (resource.isCacheable()) {
        cache.put(cacheKey, resource);
    } else {
        resourceRecycler.recycle(resource);
    }
}

这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

6. 总结

  1. with方法总结

    width方法最终目的都是通过RequestManagerRetriever对象的get方法获取RequestManager对象,传入参数主要分Application类型和非Application类型。

    (1) 如果with方法传入的是Application,会通过调用getApplicationManager()来获取一个RequestManager对象,不需要处理生命周期,因为Application对象的生命周期就是应用程序的生命周期。

    (2) 如果with方法传入的不是Application类型,最终流程都是一样,那就是会向当前的Activity当中添加一个隐藏的Fragment,通过调用fragmentGet方法创建隐藏fragment,返回RequestManager对象,创建隐藏fragment的目的是Glide需要知道加载图片加载的生命周期,可是Glide并没有办法知道Activity的生命周期,于是Glide就使用了添加隐藏Fragment的这种小技巧,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了。

    (3) 如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理,调用getApplicationManager()来获取RequestManager对象。

  2. load方法总结

    (1) 参数类型:String,File,byte[],URL,图片资源ID,Uri,我这里只看参数类型为String类型的,这些方法都会返回DrawableTypeRequest对象。

    (2) 两个重要方法是asBitmap方法和asGif方法,asBitmap方法会返回BitmapTypeRequest类型,这个方法会将图片强制转换为静态图片,asGif方法会返回GifTypeRequest类型,将图片强制转换为动态图片,如果图片是静态图片,则会加载失败。

    (3) DrawableRequestBuilder类:DrawableTypeRequest的直接父类,这里面提供了glide加载图片过程的很多方法,比如animate,centerCrop,crossFade,error,fitCenter,placeholder,skipMemoryCache,priority等等…

    (4) GenericRequestBuilder类: DrawableRequestBuilder的父类,这里面提供了绝大部分glide加载图片过程中的方法,它的子类都是直接或间接实现了这个父类。

  3. into方法总结

    (1)into方法最终会调用into(Target target)方法返回一个target对象,通过glide.buildImageViewTarget(view, transcodeClass)创建一个target对象。

    (2) 创建target对象主要分两种,如果你在使用Glide加载图片的时候调用了asBitmap()方法,那么这里就会构建出BitmapImageViewTarget对象,返回BitmapImageViewTarget对象,否则返回GlideDrawableImageViewTarget对象。

    (3) into(Target target)方法,这个方法会通过target对象获取request对象,然后清除之前的request对象,回收request对象,然后重新构建一个新的request对象,并且给这个target设置request对象,这其实就是好比listView加载图片时候给图片设置tag,防止图片错位问题,这里其实就是给target设置tag为request,也是为了防止图片错位,这里requestTracker.runRequest这个方法是执行这个请求。

    (4) buildRequest方法:构建一个request对象,然后调用target.setRequest给target设置tag,防止图片错乱。

    (5) runRequest方法:这个方法是执行图片请求的方法,这个方法内部的逻辑是判断图片当前是不是加载状态,如果是加载状态,就调用request.begin()方法,否则就把这个请求加入到等待执行的请求队列中去等待加载。

    (6) begin方法: 这个方法的逻辑是如果glide调用了override方法,指定了图片宽高,则调用onSizeReady方法,否则调用target.getSize(this)去测量图片宽高,但是最终也会通过回调形式调用onSizeReady方法。

    (7) onSizeReady方法: 这个方法里面有一些重要的对象,这个主要是调用engine.load方法去执行这个图片请求。

    (8) Engine类的load方法:

    1) 通过buildKey方法构建图片缓存key对象,参数有10多个之多,比如id,签名,图片大小,数据的编码解码等等...
    2)根据key从缓存中去获取缓存图片数据
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    3)如果缓存不为空,则会调用 cb.onResourceReady(cached)方法,加载缓存数据
    4)如果上面获取的缓存还是为空,则调用下面的方法继续去获取正在加载的图片数据
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    5)如果缓存不为空,也会调用cb.onResourceReady(active)方法去加载缓存数据。
    6)否则会通过EngineJob这个Runnable类去加载图片。
    

    (9) EngineRunnable类的run方法:run方法首先是去解码图片,然后判断有没有图片加载有没有取消,如果用户取消了加载,则回收资源,return,否则如果解码得到的Resource不为空则调用onLoadComplete加载完成的方法,加载完成通过Handler发送一个消息,更新UI,最终会调用EngineJob的handleResultOnMainThread方法,否则调用加载失败的方法,调用onException方法,也是通过Handler发送一个消息,更新UI,最终会调用handleExceptionOnMainThread方法。

    (10) 几个重要的类

    RequestManager:监听组件生命周期,管理各种图片加载,
    RequestTracker:跟踪图片请求,执行请求,删除请求,添加请求等等...
    ModeLoader:数据来源加载成原始数据
    LifecycleListener:glide绑定生命周期的回调接口
    DataLoadProvider:数据编解码
    LoadProvider:继承了DataLoadProvider
    DataFetcher:原始数据转换为我们可以用的不同数据类型,比如url,字节数组,文件等等...
    ResourceTranscoder:原始数据解码
    Engine:开启图片加载的类,两个重要方法 equals和hashCode方法
    EngineRunnable: 执行图片加载请求的子线程类
    

    (11) 图片的内存缓存是通过LruCache和弱引用的方式来实现的,正在使用中的图片使用弱引用来进行缓存,不再使用中的图片使用LruCache来进行缓存的功能,这就是Glide内存缓存的实现原理。

7. 联系方式:

QQ: 1509815887
  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值