闲来无事,就按照代码的调用方式来分析下Glide的源码,顺便方便自己以后翻看(水平有点低,欢迎留言)。
首先,我们先分析下一般的加载图片的工具类需要具有 的功能:
1、需要使用双缓存机制,对图片进行本地和内存的存储;
2、需要使用多线程对网上的图片进行下载,还需要根据需求进行裁剪;
3、需要UI线程和下载线程的交流,从而实现加载图片的要求。
4、还要考虑加载图片的一些内存回收;
姑且只能想到这4点。
一、 我们一般调用的方式是:
//使用Glide加载网络图片 public static void showImageWithGlide(Context context, final CircleImageView imageView, final String url) { imageView.setTag(url); Glide.with(context) .load(url) .placeholder(R.drawable.login_pho) .into(new SimpleTarget<GlideDrawable>() { @Override public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) { if(url.equals((String)imageView.getTag())) { imageView.setImageDrawable(resource); } } }); }
这个是我们项目中的一段代码。
二、我们来看Glide.with(context)
public static RequestManager with(Context context) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(context); }
这里用到了RequestManagerRetriever这个类,看代码的解释
这个类是一个创建新RequestManager的工具类,其中RequestManager需要Context这个变量,因此可以猜测retriever.get(context)中实现了RequestManager
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)) { 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); }这个是get代码这里只是一个封装类,将各种Context的情况进行了打包,我们选择get((Activity)context)进行跟踪。(其实这里我们一般写的时候,不是写在UI线程中的)
@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); } }这里呢,判断是不是在UI线程中,
1.如果是在UI线程中的时候呢,会调用FragmentGet函数,这里没搞懂,为啥在UI线程的时候就一定有fragment?
2.如果不是在UI线程的话,就直接调用getApplicationManger了
反正这两个最终是获得了RequestManager了,感觉说的啰嗦了。
RequestManager是一个可以管理和开始Request的类。
然后是load方法@RequestManager
public DrawableTypeRequest<String> load(String string) { return (DrawableTypeRequest<String>) fromString().load(string); }1、fromString()方法
public DrawableTypeRequest<String> fromString() { return loadGeneric(String.class); }其实可以猜测就是根据不同的参数,采用不同的加载策略,先不考虑,先看下DrawableTypeRequest,这个类是用来创建一个load request,可以加载gif亦可以加载bitmap文件。
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions其中load是在builder中的
最后在GenericRequestBuilder中的load方法中,将其放到model中
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) { this.model = model; isModelSet = true; return this; }然后是下一个流程:
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> placeholder( int resourceId) { this.placeholderId = resourceId; return this; }placeHolder的作用是
Sets an Android resource id for a {@link android.graphics.drawable.Drawable} resourceto display while a resource * is loading.
然后看into方法
public <Y extends Target<TranscodeType>> Y into(Y target) { Util.assertMainThread(); if (target == null) { throw new IllegalArgumentException("You must pass in a non null Target"); } if (!isModelSet) { throw new IllegalArgumentException("You must first set a model (try #load())"); } Request previous = target.getRequest(); if (previous != null) { previous.clear(); requestTracker.removeRequest(previous); previous.recycle(); } Request request = buildRequest(target); target.setRequest(request); lifecycle.addListener(target); requestTracker.runRequest(request); return target; }看下buildRequest,然后会调用buildRequestRecursive
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); } }好吧 这个下面再讨论,略复杂