在上篇文章中,咱们介绍了Glide图片加载框架的使用,经过以前的学习,咱们可能已经能熟练的将Glide图片加载框架运用到咱们的项目中,可是若是有人问你它是如何加载,工做原理是怎样的?为何自定义GlideModule只须要在Manifest文件中加入meta-data便可?等等不少加载流程以及使用的注意事项。固然要想搞明白这些问题,就须要咱们对Glide源码有个大体的认识,去剖析源码深处的奥秘。 接下来就让咱们一块儿去进入Glide的源码世界,本篇文章分析的是Glide 3.7.0版本。特别提醒,阅读本片文章以前要对Glide的用法要先有一个了解,能够先阅读上篇文章,详谈高大上的图片加载框架Glide -应用篇。html
此篇文章是本身学习的一个记录,若对阅读文章的你有必定帮助,非常高兴,固然文章若有不足或者错误的地方,欢迎指正,避免我给其余读者错误引导。java
若是你阅读过上篇文章,或者你使用过Glide,就知道Glide加载图片的最简单方式就是android
Glide.with(context).load(url). placeholder(R.drawable.placeholder).into(imageView)。复制代码
那么这篇文章就以这句简单的代码为主线,逐步深刻Glide的源码。缓存
//获取RequestManager对象,该类实现了LifeCycleListener接口,绑定Activity/Fragment生命周期,对请求进行暂停,恢复,清除操做
public static RequestManager with(Context context) {
//获得RequestManagerRetriever实例,该类注意将RequestManager和自定义Fragment(如RequestManagerFragment,SupportRequestManagerFragment)绑定,从而实如今生命周期管理回调
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}复制代码
Glide有四个静态的重载方法with(),其内部都经过RequestManagerRetriever相应的get重载方法获取一个RequestManager对象。RequestManagerRetriever提供各类重载方法的好处就是能够将Glide的加载请求与Activity/Fragment的生命周期绑定而自动执行请求,暂停操做。网络
接下来咱们拿Activity参数分析Glide请求如何和绑定生命周期自动请求,暂停,以及销毁。app
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
//判断activity是否已是销毁状态
assertNotDestroyed(activity);
//获取FragmentManager 对象
android.app.FragmentManager fm = activity.getFragmentManager();
//建立Fragment,RequestManager并将其绑定
return fragmentGet(activity, fm);
}
}复制代码
assertNotDestroyed主要断言Activity是否已经Destroyed。如果没有销毁,或者Activity的FragmentManager ,而后经过fragmentGet返回RequestManager。 框架
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
//*获取RequestManagerFragment,主要利用Frament进行请求的生命周期管理
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
//requestManager 为空,即首次加载初始化requestManager ,并调用setRequestManager设置到RequestManagerFragment
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
//获取Fragment对象
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;
}复制代码
最终经过getRequestManagerFragment()方法获取一个RequestManagerFragment 对象。ide
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
//省略部分代码...
@Override
public void onStart() {
super.onStart();
//关联lifecycle相应onStart方法
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
//关联lifecycle相应onStop方法
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
//关联lifecycle相应onDestroy方法
lifecycle.onDestroy();
}
}复制代码
此时咱们看到RequestManagerFragment 继承了Fragment.而且在其生命周期onStart(),onStop(),onDestory(),调用了ActivityFragmentLifecycle 相应的方法,ActivityFragmentLifecycle实现了Lifecycle 接口,在其中经过addListener(LifecycleListener listener)回调相应(LifecycleListener的 onStart(),onStop(),onDestory())周期方法。LifecycleListener是监听生命周期时间接口。 再次回到fragmentGet方法里下面一句代码函数
//建立RequestManager传入Lifecycle实现类,如ActivityFragmentLifecycle
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());复制代码
对于RequestManager类,该类实现了LifecycleListener,以下代码oop
/** * A class for managing and starting requests for Glide. Can use activity, fragment and connectivity lifecycle events to * intelligently stop, start, and restart requests. Retrieve either by instantiating a new object, or to take advantage * built in Activity and Fragment lifecycle handling, use the static Glide.load methods with your Fragment or Activity. */
public class RequestManager implements LifecycleListener {
//An interface for listening to Activity/Fragment lifecycle events.
private final Lifecycle lifecycle;
public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
}
RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext();
this.lifecycle = lifecycle;
this.treeNode = treeNode;
//A class for tracking, canceling, and restarting in progress, completed, and failed requests.
this.requestTracker = requestTracker;
//经过Glide的静态方法获取Glide实例。单例模式
this.glide = Glide.get(context);
this.optionsApplier = new OptionsApplier();
//经过工厂类ConnectivityMonitorFactory的build方法获取ConnectivityMonitor (一个用于监控网络链接事件的接口)
ConnectivityMonitor connectivityMonitor = factory.build(context,
new RequestManagerConnectivityListener(requestTracker));
// If we're the application level request manager, we may be created on a background thread. In that case we
// cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding
// ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.
if (Util.isOnBackgroundThread()) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
});
} else {
//设置监听
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}
/** * Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and restarts failed or paused requests. */
@Override
public void onStart() {
// onStart might not be called because this object may be created after the fragment/activity's onStart method.
resumeRequests();
}
/** * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and pauses in progress loads. */
@Override
public void onStop() {
pauseRequests();
}
/** * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed * requests. */
@Override
public void onDestroy() {
requestTracker.clearRequests();
}
}复制代码
它将刚建立的fragment的lifeCycle传入,并将RequestManager这个listener添加到lifeCycle中,从而实现绑定。在RequestManager的构造方法里看到了requestTracker,该对象就是跟踪请求取消,重启,完成,失败。RequestManagerFragment 主要是用来链接生命周期方法,RequestManager用来实现生命周期中请求方法,而RequestManagerRetriever绑定了RequestManager。
在构造方法中还初始化了经过Glide.get(context);初始化了Glide对象
/** * Get the singleton. * * @return the singleton */
public static Glide get(Context context) {
if (glide == null) {
//同步Glide
synchronized (Glide.class) {
if (glide == null) {
Context applicationContext = context.getApplicationContext();
//解析清单文件配置的自定义GlideModule的metadata标签,返回一个GlideModule集合
List<GlideModule> modules = new ManifestParser(applicationContext).parse();
GlideBuilder builder = new GlideBuilder(applicationContext);
//循环集合,执行GlideModule 实现类中的方法
for (GlideModule module : modules) {
module.applyOptions(applicationContext, builder);
}
glide = builder.createGlide();
for (GlideModule module : modules) {
//注册组件
module.registerComponents(applicationContext, glide);
}
}
}
}
return glide;
}复制代码
经过get方法单例方式获取实例,并在初始化时实现了GlideModule配置功能。具体怎么实现的呢?接下来具体分析一下,在初始化时new 了一个ManifestParser对象而且调用了parse()方法返回一个GlideModule类型的List.
//解析metadata具体实现
public List<GlideModule> parse() {
List<GlideModule> modules = new ArrayList<GlideModule>();
try {
//经过PackageManager获取metadata全部信息
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
//清单文件含有metadata
if (appInfo.metaData != null) {
//经过key遍历metadata(对于GlideModule,key就是GlideModule的实现类的全路径类名)
for (String key : appInfo.metaData.keySet()) {
//过滤key对应的value等于GLIDE_MODULE_VALUE(字符串GlideModule)
if (GLIDE_MODULE_VALUE.equals(appInfo.metaData.get(key))) {
//符合条件加入集合中
modules.add(parseModule(key));
}
}
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Unable to find metadata to parse GlideModules", e);
}
return modules;
}复制代码
在parse()方法中经过getApplicationInfo方法获取metaData信息,如有metaData数据(appInfo.metaData != null),若是metaData的值为GlideModule则调用parseModule(key),方法返回GlideModule并add到返回的List中。
查看parseModule(String className)方法
//经过反射获取GlideModule实例
private static GlideModule parseModule(String className) {
Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to find GlideModule implementation", e);
}
Object module;
try {
module = clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e);
}
if (!(module instanceof GlideModule)) {
throw new RuntimeException("Expected instanceof GlideModule, but found: " + module);
}
return (GlideModule) module;
}复制代码
到此咱们看到经过反射的方式获取咱们在清单文件中声明的自定义的GlideModule对象。在获取到 GlideModule集合以后,遍历了集合并调用相应的applyOptions和registerComponents方法,而Glide对象的生成是经过GlideBuilder的createGlide方法建立。
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);
//设置Bitmap池
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);
}复制代码
看到这都是作的一些初始化操做,并将参数传递到Glide构造方法。对于Glide构造方法作的都是一些默认的初始化操做,能够本身去查看源码,此处再也不贴出。
经过上面的分析,你就会理解,为何以前提到配置信息只须要实现GlideModule接口,重写其中的方法,并再清单文件配置metaData,而且metaData的key是自定义GlideModule的全路径名,value值必须是GlideModule.会明白当咱们不想让自定义的GlideModule生效时只须要删除相应的GlideModule。当使用了混淆时为何要配置...
-keep public class * implements com.bumptech.glide.module.GlideModule复制代码
对于load方法也是能够接收String,Url,Integer等类型的重载方法,在这里,咱们拿String类型参数分析。
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) {
// 省略一段代码
return optionsApplier.apply(
// 建立DrawableTypeRequest,它是GenericRequestBuilder的子类
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
}复制代码
@Override
public DrawableRequestBuilder<ModelType> load(ModelType model) {
//调用弗雷loadd方法
super.load(model);
return this;
}复制代码
返回的是DrawableTypeRequest对象,DrawableTypeRequest继承关系以下 ,而对于DrawableRequestBuilder类使用的是一个建立者模式,对于经常使用函数placeholder(),error(),transform等设置都是在此设置,
/** * {@inheritDoc} */
@Override
public DrawableRequestBuilder<ModelType> placeholder(Drawable drawable) {
super.placeholder(drawable);
return this;
}复制代码
咱们看到最终又调用了父类方法
/** * Sets an Android resource id for a {@link android.graphics.drawable.Drawable} resourceto display while a resource * is loading. * * @param resourceId The id of the resource to use as a placeholder * @return This request builder. */
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> placeholder( int resourceId) {
this.placeholderId = resourceId;
return this;
}复制代码
经过查看父类(GenericRequestBuilder)源码你会发现咱们每次调用placeholder(),error()的等这些方法,其实都是给该类中的变量赋值。
通过一系列操做后,最终调用into(imageView)方法来完成图片的最终加载
/** * Sets the {@link ImageView} the resource will be loaded into, cancels any existing loads into the view, and frees * any resources Glide may have previously loaded into the view so they may be reused. * * @see Glide#clear(android.view.View) * * @param view The view to cancel previous loads for and load the new resource into. * @return The {@link com.bumptech.glide.request.target.Target} used to wrap the given {@link ImageView}. */
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}复制代码
由上面看到最终调用的into方法是
/** * Set the target the resource will be loaded into. * * @see Glide#clear(com.bumptech.glide.request.target.Target) * * @param target The target to load the resource into. * @return The given 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 对象
Request previous = target.getRequest();
//requestTracker是请求跟踪类对象,主要管理请求的发起,暂停,清除
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
//建立请求对象
Request request = buildRequest(target);
target.setRequest(request);
//将target加入lifecycle
lifecycle.addListener(target);
//执行请求
requestTracker.runRequest(request);
return target;
}复制代码
上面都执行都调用了 Util.assertMainThread();判断只能在主线程中执行。(更新View固然须要在主线程),在Glide中Target咱们能够理解成View,只是Glide对咱们的View作了一层封装。 以后经过buildRequest建立请求对象。
//建立请求对象
private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
//默认加载优先级 NORMAL
priority = Priority.NORMAL;
}
//建立Request
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);
}
}复制代码
最后调用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(...) {
@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对象
request.init(...);
//返回Request对象
return request;
}复制代码
至此请求对象建立成功,在经过buildRequest建立请求成功后,使用了target.setRequest(request);将请求设置到target,并经过addListener将target加入到lifecycle。上面执行了那么多都只是请求建立,请求的执行时经过requestTracker.runRequest(request);开始的。
/** * Starts tracking the given request. */
public void runRequest(Request request) {
//添加request对象到集合中
requests.add(request);
if (!isPaused) {
//若是当前状态是非暂停的,调用begin方法发送请求
request.begin();
} else {
//将请求加入到挂起的请求集合
pendingRequests.add(request);
}
}复制代码
在上面几句代码,咱们看到,每次提交请求都将请求加入了一个set中,用它来管理请求,而后经过request的实现类GenericRequest查看begin方法执行的内容
/** * {@inheritDoc} */
@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));
}
}
//获取设置加载开始时占位图片的Drawable 对象
private Drawable getPlaceholderDrawable() {
if (placeholderDrawable == null && placeholderResourceId > 0) {
placeholderDrawable = context.getResources().getDrawable(placeholderResourceId);
}
return placeholderDrawable;
}复制代码
上面有一句!isComplete() && !isFailed() && canNotifyStatusChanged()判断,若是都为真会回调target.onLoadStarted(getPlaceholderDrawable());咱们能够看到Target的实现类ImageViewTarget中onLoadStarted的回调执行语句
//给ImageView设置Drawable
@Override
public void onLoadStarted(Drawable placeholder) {
view.setImageDrawable(placeholder);
}复制代码
如今你是否是有一种柳暗花明又一村的感受,终于明白为何设置placeHolder后,会在加载前有一个占位图,固然设置加载错误图片占位图的原理也是同样的。只不过回调执行时机不一样。
/** * A callback method that should never be invoked directly. */
@Override
public void onSizeReady(int width, int height) {
//省略部分代码
status = Status.RUNNING;//将请求状态更新为运行状态
//省略部分代码
// 进入Engine的入口,请求执行的核心方法
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));
}
}复制代码
Engine类封装了数据获取的重要入口方法,向request层提供这些API,好比load(), release(), clearDiskCache()等方法
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
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) {
// 获取数据成功,会回调target的onResourceReady()
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
// 尝试从活动Resources 中获取,它表示的是当前正在使用的Resources,与内存缓存不一样之处是clear缓存时不会clear它。
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);
//判断jobs中是否已经存在任务,若是存在说明任务以前已经提交了
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 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 是任务执行阶段的入口
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
// 开始提交job
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}复制代码
咱们看到先根据调用loadFromCache从内存加载,若返回值为空再次从活动的资源中加载,若再次为空查看jobs是否提交过任务,若没有提交则建立EngineRunnable,并将任务提交到engineJob中。咱们先看下EngineJob中的start方法
//提交任务,将任务加入到线程池
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
//提交任务到diskCacheService线程池
future = diskCacheService.submit(engineRunnable);
}复制代码
接下来看线程类EngineRunnable的run方法,它是任务执行的入口
//任务运行入口
@Override
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
//数据的获取,编解码
resource = decode();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
exception = e;
}
//若是当前状态是取消,则回收各类资源防止内存泄露
if (isCancelled) {
if (resource != null) {
resource.recycle();
}
return;
}
if (resource == null) {
//加载失败回调
onLoadFailed(exception);
} else {
//加载成功回调
onLoadComplete(resource);
}
}
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
//// 从DiskLruCache中获取数据并解码
return decodeFromCache();
} else {
// 从其余途径获取数据并解码,如网络,本地File,数据流等
return decodeFromSource();
}
}复制代码
##DiskLruCache获取数据 ##
private Resource<?> decodeFromCache() throws Exception {
Resource<?> result = null;
try {
result = decodeJob.decodeResultFromCache();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Exception decoding result from cache: " + e);
}
}
if (result == null) {
result = decodeJob.decodeSourceFromCache();
}
return result;
}复制代码
以后调用decodeJob类中的decodeResultFromCache
public Resource<Z> decodeResultFromCache() throws Exception {
if (!diskCacheStrategy.cacheResult()) {
return null;
}
long startTime = LogTime.getLogTime();
//从DiskCache中获取资源
Resource<T> transformed = loadFromCache(resultKey);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded transformed from cache", startTime);
}
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from cache", startTime);
}
return result;
}
//从DiskCache中获取资源
private Resource<T> loadFromCache(Key key) throws IOException {
//根据key从DiskCache获取文件
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}复制代码
接下来咱们分析decodeFromSource方法
// 调用decodeJob来完成数据获取和编解码
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
public Resource<Z> decodeFromSource() throws Exception {
// 获取数据,解码
Resource<T> decoded = decodeSource();
//编码并保存
return transformEncodeAndTranscode(decoded);
}
// 获取数据,解码
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
//数据拉取
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
//编码
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}复制代码
在数据获取时先调用DataFetcher的loadData()拉取数据,对于DataFetcher的实现类有好几个,咱们拿从url拉取数据为例,也就是HttpUrlFetcher类
@Override
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
}
//返回InputStream 对象
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new IOException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
// 静态工厂模式建立HttpURLConnection对象
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
//设置请求参数
//设置链接超时时间2500ms
urlConnection.setConnectTimeout(2500);
//设置读取超时时间2500ms
urlConnection.setReadTimeout(2500);
//不使用http缓存
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
//请求成功
return getStreamForSuccessfulRequest(urlConnection);
} else if (statusCode / 100 == 3) {
//
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new IOException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else {
if (statusCode == -1) {
throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
}
throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
}
}复制代码
看到这终于看到了网络加载请求,咱们也能够自定义DataFetcher,从而使用其余网络库,如OkHttp,Volley. 最后咱们再看下transformEncodeAndTranscode方法
private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
long startTime = LogTime.getLogTime();
// 根据ImageView的scaleType等参数计算真正被ImageView使用的图片宽高,并保存真正宽高的图片。
Resource<T> transformed = transform(decoded);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transformed resource from source", startTime);
}
// 写入到DiskLruCache中,下次就能够直接从DiskLruCache获取使用
writeTransformedToCache(transformed);
startTime = LogTime.getLogTime();
// 转码,将源图片转码为ImageView所需的图片格式
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from source", startTime);
}
return result;
}复制代码
至此,图片加载流程已经介绍完毕,固然还有不少的地方没有提到,相信若是你在阅读本文的同时,本身跟踪源码会轻松不少,若是本身不跟着源码走的话,可能这篇文章看几遍对Glide原理理解的也是云里雾里,或者说当时看的懂,可是很快就不记得。因此切记本身要跟着源码过一遍。
本片文章实在是长,能读完本文章也是须要必定毅力的...若文章有不足或者错误的地方,欢迎指正,以防止给其余读者错误引导。