超详细的Glide源码解析

我与影子孤独终老i 提交于 2021-02-04 19:13:13

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;}
@Overridepublic void onStart() {    super.onStart();    lifecycle.onStart();}
@Overridepublic void onStop() {    super.onStop();    lifecycle.onStop();}
@Overridepublic 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)方法:
@Overridepublic 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;}
@Overridepublic void setRequest(Request request) {    setTag(request);}

 

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

4.4 recycle方法

@Overridepublic 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请求的方法

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

@Overridepublic 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 内存缓存的写入操作

@Overridepublic 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")@Overridepublic 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对象

@Overridepublic 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:继承了DataLoadProviderDataFetcher:原始数据转换为我们可以用的不同数据类型,比如url,字节数组,文件等等...ResourceTranscoder:原始数据解码Engine:开启图片加载的类,两个重要方法 equals和hashCode方法EngineRunnable: 执行图片加载请求的子线程类

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

 

欢迎关注我的公众号,一起进步!

图片

本文分享自微信公众号 - Android架构师成长之路(gh_07f996f00d9b)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!