Glide是比较常用的图片加载库,因为我在项目里使用到了,所以会跟EventBus一样参考网上前辈的文章做一个学习笔记。
图片加载是 Android 项目中必备的需求,而图片加载的开源库也有很多:有 UniversalImageLoader、Picasso、Fresco、Glide等。
Glide.with(imageView.getContext())
.load(url)
.placeholder(defaultImage)
.error(failImage)
.into(imageView);
如上,Glide 库使用流接口(fluent interface)。流接口(fluent Interface)是指实现一种实现面向对象的能提高代码可读性的API的方法。Glide可以从资源,文件目录和网络上加载图片资源。当加载图片时,Glide 使用3个来源:内存,磁盘和网络(从最快到最慢排序)。Glide 建造者要求最少有三个参数:
with(Context context) ;load(String imageUrl) - 这里你可以指定哪个图片应该被加载,同上它会是一个字符串的形式表示一个网络图片的 URL;into(ImageView targetImageView) 你的图片会显示到对应的 ImageView 中。
如上一段的代码可以看出,调用了Glide类的with方法(例子里使用的是第一个)。
////获取RequestManager对象,该类实现了LifeCycleListener接口,绑定Activity/Fragment生命周期,对请求进行暂停,恢复,清除操作。
public static RequestManager with(Context context) {//获取RequestManager对象
//得到RequestManagerRetriever实例,该类将RequestManager和自定义Fragment(如RequestManagerFragment,SupportRequestManagerFragment)绑定,从而实现在生命周期管理回调。这里自定义Fragment值得注意。
RequestManagerRetriever retriever = RequestManagerRetriever.get();//新建一个handler,handler = new Handler(Looper.getMainLooper(), this /* Callback */);RequestManagerRetriever实现了Handler.Callback。
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);
}
可以看出,5个函数都是起先调用了RequestManagerRetriever retriever = RequestManagerRetriever.get()。他们最后都创建了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)) {//判断是不是主线程,并且context不是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);
}
在这里,特别提到ContextWrapper,它与context的关系如下图:
如果我调用了Glide.with(imageView.getContext())的话,那么应该调用return get((FragmentActivity) context);步骤。
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {//判断是否在主线程
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);//判断界面是否已经销毁了
FragmentManager fm = activity.getSupportFragmentManager();//获取FragmentManager 对象(android.support.v4.app包带的)
return supportFragmentGet(activity, fm);//创建Fragment,RequestManager并将其绑定
}
}
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
//获取RequestManagerFragment,主要利用Frament进行请求生命周期管理
SupportRequestManagerFragment current = getSupportRequestManagerFragment(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;
}
SupportRequestManagerFragment 是一个无界面的Fragment类,起到把请求和Activity生命周期同步的作用。上面代码主要的部分就是getSupportRequestManagerFragment函数,获取到了一个fragment。
RequestManagerFragment getRequestManagerFragment(FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment)fm.findFragmentByTag("com.bumptech.glide.manager");//强转,看看有没有以当前tag命名的fragment,不为空的话直接返回,为空的话需要创建。
if(current == null) {
current = (RequestManagerFragment)this.pendingRequestManagerFragments.get(fm);//pendingRequestManagerFragments是一个hashmap,创建的RequestManagerFragment 对象会存放在其中,复用。
if(current == null) {
current = new RequestManagerFragment();
this.pendingRequestManagerFragments.put(fm, current);//存放在hashmap里。
fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();
this.handler.obtainMessage(1, fm).sendToTarget();//发送消息,同时会把hashmap中的fragment移除(代码不贴了)
}
}
return current;
}
上面的代码中,创建RequestManagerFragment是比较关键的一步。
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
private final RequestManagerTreeNode requestManagerTreeNode;
private RequestManager requestManager;
private final HashSet childRequestManagerFragments;
private RequestManagerFragment rootRequestManagerFragment;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@SuppressLint({"ValidFragment"})
RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
this.requestManagerTreeNode = new RequestManagerFragment.FragmentRequestManagerTreeNode();
this.childRequestManagerFragments = new HashSet();
this.lifecycle = lifecycle;
}
//中间省略一些方法
public void onStart() {
super.onStart();
this.lifecycle.onStart();//调用lifecycle相应onStart方法
}
public void onStop() {
super.onStop();
this.lifecycle.onStop();//调用lifecycle相应onStop方法
}
public void onDestroy() {
super.onDestroy();
this.lifecycle.onDestroy();//调用lifecycle相应onDestroy方法
}
}
RequestManagerFragment 继承了Fragment。并且在其生命周期onStart(),onStop(),onDestory()中调用了ActivityFragmentLifecycle 中相应的方法。ActivityFragmentLifecycle实现了Lifecycle 接口,其中定义了onStart()等函数的具体实现。
经过上面这么多步骤,得到的RequestManagerFragment将作为参数创建RequestManager对象。load函数位于RequestManager类中。
RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode, RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext();
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.glide = Glide.get(context);//获取Glide实例,不同于一般的单例
this.optionsApplier = new RequestManager.OptionsApplier();
ConnectivityMonitor connectivityMonitor = factory.build(context, new RequestManager.RequestManagerConnectivityListener(requestTracker));//通过工厂类ConnectivityMonitorFactory的build方法获取ConnectivityMonitor (一个用于监控网络连接事件的接口)
if(Util.isOnBackgroundThread()) {
(new Handler(Looper.getMainLooper())).post(new Runnable() {
public void run() {
lifecycle.addListener(RequestManager.this);
}
});
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}
构造函数将刚创建的fragment的lifeCycle传入,并将RequestManager这个listener添加到lifeCycle中,从而实现绑定。在RequestManager的构造方法里看到了requestTracker,该对象就是跟踪请求取消,重启,完成,失败;requestTracker在生命周期函数中都执行了。RequestManagerFragment 主要是用来连接生命周期方法,RequestManager用来实现生命周期中请求方法,而RequestManagerRetriever绑定了RequestManager。
public static Glide get(Context context) {
if(glide == null) {
Class var1 = Glide.class;
synchronized(Glide.class) {
if(glide == null) {//首先这是一个基本的单例
Context applicationContext = context.getApplicationContext();//获取ApplicationContext
//解析清单文件配置的自定义GlideModule的metadata标签,返回一个GlideModule集合
List modules = (new ManifestParser(applicationContext)).parse();//parse函数见下一个模块
GlideBuilder builder = new GlideBuilder(applicationContext);
Iterator i$ = modules.iterator();
GlideModule module;
//循环集合,执行GlideModule 实现类中的方法
while(i$.hasNext()) {
module = (GlideModule)i$.next();
module.applyOptions(applicationContext, builder);
}
glide = builder.createGlide();//初始化了很多变量,如Engine对象等。
i$ = modules.iterator();
while(i$.hasNext()) {
module = (GlideModule)i$.next();
//注册组件
module.registerComponents(applicationContext, glide);
}
}
}
}
return glide;
}
com.bumptech.glide.module/ManifestParser
public List parse() {
ArrayList modules = new ArrayList();
try {
ApplicationInfo e = this.context.getPackageManager().getApplicationInfo(this.context.getPackageName(), 128);//128在github上的最新代码里替换为了PackageManager.GET_META_DATA,通过PackageManager获取metadata所有信息。
if(e.metaData != null) {//清单文件含有metadata
Iterator i$ = e.metaData.keySet().iterator();
//遍历metadata
while(i$.hasNext()) {
String key = (String)i$.next();
if("GlideModule".equals(e.metaData.get(key))) {找到匹配字符串“GlideModule”
modules.add(parseModule(key));
}
}
}
return modules;
} catch (NameNotFoundException var5) {
throw new RuntimeException("Unable to find metadata to parse GlideModules", var5);
}
}
上面函数中parseModule(key)返回的结果最后add在了ArrayList里。
private static GlideModule parseModule(String className) {//通过反射获取GlideModule实例,className是类的路径
Class clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException var6) {
throw new IllegalArgumentException("Unable to find GlideModule implementation", var6);
}
Object module;
try {
module = clazz.newInstance();//反射获取对象
} catch (InstantiationException var4) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, var4);
} catch (IllegalAccessException var5) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, var5);
}
if(!(module instanceof GlideModule)) {
throw new RuntimeException("Expected instanceof GlideModule, but found: " + module);
} else {
return (GlideModule)module;
}
}
com.bumptech.glide/GlideBuilder.java
Glide createGlide() {
if(this.sourceService == null) {
int calculator = Math.max(1, Runtime.getRuntime().availableProcessors());
this.sourceService = new FifoPriorityThreadPoolExecutor(calculator);//初始化线程池
}
if(this.diskCacheService == null) {
this.diskCacheService = new FifoPriorityThreadPoolExecutor(1);
}
MemorySizeCalculator calculator1 = new MemorySizeCalculator(this.context);
if(this.bitmapPool == null) { //设置Bitmap池
if(VERSION.SDK_INT >= 11) {
int size = calculator1.getBitmapPoolSize();
this.bitmapPool = new LruBitmapPool(size);
} else {
this.bitmapPool = new BitmapPoolAdapter();
}
}
if(this.memoryCache == null) {
this.memoryCache = new LruResourceCache(calculator1.getMemoryCacheSize());
}
if(this.diskCacheFactory == null) {//内部磁盘缓存
this.diskCacheFactory = new InternalCacheDiskCacheFactory(this.context);
}
if(this.engine == null) { //初始化引擎类
this.engine = new Engine(this.memoryCache, this.diskCacheFactory, this.diskCacheService, this.sourceService);
}
if(this.decodeFormat == null) {
this.decodeFormat = DecodeFormat.DEFAULT;//默认解码格式PREFER_RGB_565
}
return new Glide(this.engine, this.memoryCache, this.bitmapPool, this.context, this.decodeFormat);
}
上面的分析,主要是下面的用法准备的:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bumptech.glide.integration.volley">
<application>
<meta-data
android:name="com.bumptech.glide.integration.volley.VolleyGlideModule"
android:value="GlideModule"/>//GlideModule去寻找name也就是key
application>
manifest>
关于GlideModule,我也不太懂。。。
RequestManager创建完毕后,我们调用了load方法。以我上面的例子来看,我传入的是string(url),也就是调用了下面的函数:
RequestManager.java
public DrawableTypeRequest load(String string) {
return (DrawableTypeRequest)this.fromString().load(string);
}
public DrawableTypeRequest fromString() {
return this.loadGeneric(String.class);
}
private DrawableTypeRequest loadGeneric(Class modelClass) {
ModelLoader streamModelLoader = Glide.buildStreamModelLoader(modelClass, this.context);
ModelLoader fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, this.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");
} else {
return (DrawableTypeRequest)this.optionsApplier.apply(new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, this.context, this.glide, this.requestTracker, this.lifecycle, this.optionsApplier));
}// 创建DrawableTypeRequest,它是GenericRequestBuilder的子类
}
DrawableRequestBuilder.java
public DrawableRequestBuilder load(ModelType model) {
super.load(model);//调用父类方法,如下
return this;
}
DrawableRequestBuilder.java
public GenericRequestBuilder load(ModelType model) {
this.model = model;
this.isModelSet = true;
return this;//GenericRequestBuilder返回自身对象
}
placeholder,error和into等函数在DrawableRequestBuilder中都定义了,但是它们最终都调用的是DrawableRequestBuilder中的函数,这里其实就是一个建造者模式了,可以链式书写代码,初始化其中的属性,并且最终调用了into函数来进行请求。
public Target into(ImageView view) {
Util.assertMainThread();
if(view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
} else {
if(!this.isTransformationSet && view.getScaleType() != null) {
switch(GenericRequestBuilder.SyntheticClass_1.$SwitchMap$android$widget$ImageView$ScaleType[view.getScaleType().ordinal()]) {
case 1:
this.applyCenterCrop();
break;
case 2:
case 3:
case 4:
this.applyFitCenter();
}
}
return this.into(this.glide.buildImageViewTarget(view, this.transcodeClass));//跟代码最后发现函数最终执行到了当前类的obtainRequest函数,发起了请求。
}
}
上面的函数调用到了下面的函数:
public > Y into(Y target) {
Util.assertMainThread();
if(target == null) {
throw new IllegalArgumentException("You must pass in a non null Target");
} else if(!this.isModelSet) {
throw new IllegalArgumentException("You must first set a model (try #load())");
} else {
//获取Request 对象
Request previous = target.getRequest();
if(previous != null) {//复用
previous.clear();
this.requestTracker.removeRequest(previous);//requestTracker是请求跟踪类对象,主要管理请求的发起,暂停,清除
previous.recycle();
}
Request request = this.buildRequest(target);//创建请求对象,如下
target.setRequest(request);
this.lifecycle.addListener(target);//将target加入lifecycle
this.requestTracker.runRequest(request);//执行请求
return target;
}
}
buildRequestRecursive实则调用了buildRequestRecursive函数。
private Request buildRequestRecursive(Target target, ThumbnailRequestCoordinator parentCoordinator) {
ThumbnailRequestCoordinator coordinator;
Request fullRequest;
Request thumbnailRequest;
if(this.thumbnailRequestBuilder != null) {//如果配置了thumbnail(缩略图)请求,则构建一个ThumbnailRequestCoordinator(包含了FullRequest和ThumbnailRequest)请求,否则简单的构建一个Request
if(this.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()");
} else {
if(this.thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) {
this.thumbnailRequestBuilder.animationFactory = this.animationFactory;
}
if(this.thumbnailRequestBuilder.priority == null) {
this.thumbnailRequestBuilder.priority = this.getThumbnailPriority();
}
if(Util.isValidDimensions(this.overrideWidth, this.overrideHeight) && !Util.isValidDimensions(this.thumbnailRequestBuilder.overrideWidth, this.thumbnailRequestBuilder.overrideHeight)) {
this.thumbnailRequestBuilder.override(this.overrideWidth, this.overrideHeight);
}
coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
fullRequest = this.obtainRequest(target, this.sizeMultiplier.floatValue(), this.priority, coordinator);
this.isThumbnailBuilt = true;
thumbnailRequest = this.thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
this.isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
}
} else if(this.thumbSizeMultiplier != null) {
coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
fullRequest = this.obtainRequest(target, this.sizeMultiplier.floatValue(), this.priority, coordinator);
thumbnailRequest = this.obtainRequest(target, this.thumbSizeMultiplier.floatValue(), this.getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
return this.obtainRequest(target, this.sizeMultiplier.floatValue(), this.priority, parentCoordinator);
}
}
最终调用了obtainRequest函数。至此请求对象创建成功。
public void runRequest(Request request) {
this.requests.add(request);//添加request对象到集合中,requests是一个set,Set是一个不包含重复元素的 collection,在这里是无序的。
if(!this.isPaused) {
request.begin();//如果当前状态是非暂停的,调用begin方法发送请求
} else {
this.pendingRequests.add(request);//将请求加入到挂起的请求集合,RequestTracker在RequestManager类中初始化,并且跟踪着生命周期
}
}
GenericRequest.java,通过request的实现类GenericRequest查看begin方法执行的内容。
public void begin() {
this.startTime = LogTime.getLogTime();
if(this.model == null) {/加载错误占位图设置
this.onException((Exception)null);
} else {
this.status = GenericRequest.Status.WAITING_FOR_SIZE;
//验证宽高是否合法
//发送请求
this.onSizeReady(this.overrideWidth, this.overrideHeight);
} else {
this.target.getSize(this);
}
if(!this.isComplete() && !this.isFailed() && this.canNotifyStatusChanged()) {//加载前默认占位图设置回调,应该会在 this.onSizeReady(this.overrideWidth, this.overrideHeight);前面执行完。
this.target.onLoadStarted(this.getPlaceholderDrawable());
}
if(Log.isLoggable("GenericRequest", 2)) {
this.logV("finished run method in " + LogTime.getElapsedMillis(this.startTime));
}
}
}
public void onSizeReady(int width, int height) {
if(Log.isLoggable("GenericRequest", 2)) {
this.logV("Got onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
}
if(this.status == GenericRequest.Status.WAITING_FOR_SIZE) {
this.status = GenericRequest.Status.RUNNING;//将请求状态更新为运行状态
width = Math.round(this.sizeMultiplier * (float)width);
height = Math.round(this.sizeMultiplier * (float)height);
ModelLoader modelLoader = this.loadProvider.getModelLoader();
DataFetcher dataFetcher = modelLoader.getResourceFetcher(this.model, width, height);
if(dataFetcher == null) {
this.onException(new Exception("Failed to load model: \'" + this.model + "\'"));
} else {
ResourceTranscoder transcoder = this.loadProvider.getTranscoder();
if(Log.isLoggable("GenericRequest", 2)) {
this.logV("finished setup for calling load in " + LogTime.getElapsedMillis(this.startTime));
}
this.loadedFromMemoryCache = true;
this.loadStatus = this.engine.load(this.signature, width, height, dataFetcher, this.loadProvider, this.transformation, transcoder, this.priority, this.isMemoryCacheable, this.diskCacheStrategy, this);//进入Engine逻辑
this.loadedFromMemoryCache = this.resource != null;
if(Log.isLoggable("GenericRequest", 2)) {
this.logV("finished onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
}
}
}
}
Engine类封装了数据获取的重要入口方法,向request层提供如load(), release()等方法,Engine主要负责图片加载。
public Engine.LoadStatus load(Key signature, int width, int height, DataFetcher fetcher, DataLoadProvider loadProvider, Transformation transformation, ResourceTranscoder transcoder, Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
Util.assertMainThread();//判断是否在主线程
long startTime = LogTime.getLogTime();
String id = fetcher.getId();
//创建Enginekey,这是给每次加载资源的唯一标示。
EngineKey key = this.keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(), loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(), transcoder, loadProvider.getSourceEncoder());
//从缓存加载图片, 从内存缓存中获取资源,获取成功后会放入到activeResources中
EngineResource cached = this.loadFromCache(key, isMemoryCacheable);
if(cached != null) {
// 获取数据成功,会回调onResourceReady方法。
cb.onResourceReady(cached);
if(Log.isLoggable("Engine", 2)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
} else {
// 尝试从活动Resources 中获取,它表示的是当前正在使用的Resources,与内存缓存不同之处是clear缓存时不会clear它。
EngineResource active = this.loadFromActiveResources(key, isMemoryCacheable);
if(active != null) {
cb.onResourceReady(active);//回调
if(Log.isLoggable("Engine", 2)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
} else {
EngineJob current = (EngineJob)this.jobs.get(key);
if(current != null) {//判断jobs中是否已经存在任务,如果存在说明任务之前已经提交了
current.addCallback(cb);
if(Log.isLoggable("Engine", 2)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new Engine.LoadStatus(cb, current);
} else {//缓存没有获取到,创建EngineJob 对象
EngineJob engineJob = this.engineJobFactory.build(key, isMemoryCacheable);
DecodeJob decodeJob = new DecodeJob(key, width, height, fetcher, loadProvider, transformation, transcoder, this.diskCacheProvider, diskCacheStrategy, priority); //EngineRunnable 是任务执行阶段的入口
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
this.jobs.put(key, engineJob);
engineJob.addCallback(cb);
// 开始提交job,线程池执行函数
engineJob.start(runnable);
if(Log.isLoggable("Engine", 2)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new Engine.LoadStatus(cb, engineJob);
}
}
}
}
先根据调用loadFromCache从内存加载,若返回值为空再次从活动的资源中加载,若再次为空查看jobs是否提交过任务,若没有提交则创建EngineRunnable,并将任务提交到engineJob中。
Transformation类负责处理资源,这里面出现BitmapPool类,达到Bitmap复用。
先从cache中寻找资源,如果找到则将其从cache中移除并放入activeResources中,否则从activeResources中寻找。cache是LruResourceCache对象,作为资源的LRU缓存;activeResources是以弱引用为值的Map,用于缓存使用中的资源。比一般内存缓存额外多一级缓存的意义在于,当内存不足时清理cache中的资源时,不会对使用中的Bitmap造成影响。
DecodeJob是整个任务的核心部分,它的流程图如下:
转自:Glide源码分析
这里主要是内存缓存。
EngineRunnable实现了Runnable接口。
public void run() {
if(!this.isCancelled) {
Exception exception = null;
Resource resource = null;
try {
resource = this.decode();//数据的获取,编解码
} catch (Exception var4) {
if(Log.isLoggable("EngineRunnable", 2)) {
Log.v("EngineRunnable", "Exception decoding", var4);
}
exception = var4;
}
if(this.isCancelled) {//如果当前状态是取消,则回收各种资源防止内存泄露
if(resource != null) {
resource.recycle();
}
} else {
if(resource == null) {//加载失败回调
this.onLoadFailed(exception);
} else {
this.onLoadComplete(resource);//加载成功回调
}
}
}
}
private Resource> decode() throws Exception {
return this.isDecodingFromCache()?this.decodeFromCache():this.decodeFromSource();//如果图片是本地缓存里的,那么就执行decodeFromCache;否则执行decodeFromSource。
}
private Resource> decodeFromCache() throws Exception {
Resource result = null;
try {
result = this.decodeJob.decodeResultFromCache();//取到Resource
} catch (Exception var3) {
if(Log.isLoggable("EngineRunnable", 3)) {
Log.d("EngineRunnable", "Exception decoding result from cache: " + var3);
}
}
if(result == null) {
result = this.decodeJob.decodeSourceFromCache();//为空的话创建一个,否则直接返回Resource对象。
}
return result;
}
DecodeJob.java
DecodeJob.java实现了Runnable接口,调度任务的核心类,整个请求的繁重工作都在这里完成:处理来自缓存或者原始的资源,应用转换动画以及transcode。
public Resource decodeResultFromCache() throws Exception {
if(!this.diskCacheStrategy.cacheResult()) {
return null;
} else {
long startTime = LogTime.getLogTime();
Resource transformed = this.loadFromCache(this.resultKey);//从DiskCache中获取资源
if(Log.isLoggable("DecodeJob", 2)) {
this.logWithTimeAndKey("Decoded transformed from cache", startTime);
}
startTime = LogTime.getLogTime();
Resource result = this.transcode(transformed);
if(Log.isLoggable("DecodeJob", 2)) {
this.logWithTimeAndKey("Transcoded transformed from cache", startTime);
}
return result;
}
}
decodeResultFromCache方法从磁盘缓存中获取对应Bitmap并将其转码。
decodeSourceFromCache方法从磁盘缓存中获取对应Bitmap并将其转换。
另一条逻辑是执行decodeFromSource(对应decodeFromCache函数)。
public Resource decodeFromSource() throws Exception {
Resource decoded = this.decodeSource();
return this.transformEncodeAndTranscode(decoded);//编码之后通过transformEncodeAndTranscode方法进行转换处理。
}
// 调用decodeJob来完成数据获取和编解码
private Resource decodeSource() throws Exception {
Resource decoded = null;
Object var5;
try {
long startTime = LogTime.getLogTime();
//数据拉取
Object data = this.fetcher.loadData(this.priority);//获取数据
if(Log.isLoggable("DecodeJob", 2)) {
this.logWithTimeAndKey("Fetched data", startTime);
}
if(!this.isCancelled) {
decoded = this.decodeFromSourceData(data);//编码
return decoded;
}
var5 = null;
} finally {
this.fetcher.cleanup();
}
return (Resource)var5;
}
最后调用transformEncodeAndTranscode函数保存DiskLruCache函数。后半部分的源码我自己看的也是晕乎乎的,如果有更好的方法,麻烦告知一下~
Glide优点在于其生命周期的管理,资源类型的支持多,内存也较为友好。Glide的架构扩展性高,但是难以理解,各种接口、泛型,需要一定的学习才能熟练运用(源码对于我来说难度很高~)。它支持对处理后的资源Disk缓存;能通过BitmapPool对Bitmap复用,还能使用activityResources缓存正在使用的resource,对于BitmapPool饱和移除的Bitmap直接调用recycle加速内存回收。本文主要是个人学习做的一个笔记,中间借鉴了详谈高大上的图片加载框架Glide -源码篇这个前辈的文章。主要是走了一遍流程,感觉Glide的源码相对于开源的一些UI控件,还是更为复杂,所以很多步骤没有写完,并不是很完整。里面夹杂了一些自己的理解,如果有错误,希望您能指出,共同进步~
Glide - 开始!
ANDROID开源项目推荐之「图片加载到底哪家强」
Glide - 回调:SimpleTarget 和 ViewTarget 用于自定义视图类
Glide源码分析
详谈高大上的图片加载框架Glide -源码篇
Glide 源码解析
Glide源码分析