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. 总结
-
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对象。
-
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加载图片过程中的方法,它的子类都是直接或间接实现了这个父类。
-
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内存缓存的实现原理。
欢迎关注我的公众号,一起进步!
本文分享自微信公众号 - Android架构师成长之路(gh_07f996f00d9b)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4611086/blog/4945108