首先Glide作为一个强大的图片加载框架,已经被android官方使用,所以,明白Glide的加载流程以及原理对加深我们对glide的理解是很重要的。下面我们就来分析下 Glide 执行流程,脑袋里面先有一个对 Glide 源码总体执行流程的认识,借鉴一张艽野尘梦绘制的Glide框架图,让我们对Glide的总体框架有一个初步的了解
首先我们从这一句入手,先看看Glide的初始化过程,也就是Glide.with(this)这个方法。
Glide.with(this).load("").into(new ImageView(this));
with
1 调用with
Glide.with(Activity);
看下 with 这个源码函数,重载有很多。
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/** @deprecated */
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
其实常用的就 Activity,Fragment, Context 这 3 种形式,下面我们就以 Activity 为主。
2 getRetriever(activity)
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
Preconditions.checkNotNull(context, "You cannot start a load on a not yet attached View or a Fragment where getActivity() returns null (which usually occurs when getActivity() is called before the Fragment is attached or after the Fragment is destroyed).");
return get(context).getRequestManagerRetriever();
}
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
Class var1 = Glide.class;
synchronized(Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
//这里会抛出初始化异常的信息
} else {
//是否初始化标志
isInitializing = true;
//开始进行初始化
initializeGlide(context);
isInitializing = false;
}
}
private static void initializeGlide(@NonNull Context context) {
//实例化一个 GlideBuilder 在进行初始化
//GlideBuilder 默认的一些配置信息
initializeGlide(context, new GlideBuilder());
}
通过调用getRetriever 方法 实例化一个 GlideBuilder 进行初始化信息 。
下面我们来看 initializeGlide(context, new GlideBuilder()) 具体做了些什么
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
//通过反射找到GeneratedAppGlideModuleImpl 类,如果能找到,就说明自定义了GlideModule
//那么就需要在合适的地方调用applyOptions、registerComponents 来实现自定义的功能
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
// 从AndroidManifest.xml 获取自定义的GlideModule(这是另外一种自定义GlideModule的方式)
manifestModules = new ManifestParser(applicationContext).parse();
}
//如果在注解中指明了要排除的GlideModule,则把GlideModule删除,在GlideModule中 从AndroidManifest.xml 中获取的
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
com.bumptech.glide.module.GlideModule current = iterator.next();
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
// 获取工厂,用于创建RequestManager(该工厂用于,如果with()参数传递的是application)
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
//执行用户在 manifest 中配置的 GlideModule 接口中的方法
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
//执行使用注解配置的GlideModule 接口中的方法
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//1 创建Glide,分析
Glide glide = builder.build(applicationContext);
//下面registerComponents 方法的执行,需要传递Registry对象,而该对象是在创建Glide 的时候,被赋值,并设置一系列的参数
//执行用户在 manifest 中配置的 GlideModule 接口中的registerComponents 方法
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
//执行 使用注解配置的GlideModule 接口中的registerComponents 方法
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
//向单例赋值
Glide.glide = glide;
}
我们通过注释1 看到通过建造者模式创建了一个 Glide 对象,我们现在来看看内部怎么实现的
Glide build(@NonNull Context context) {
//创建执行器,用于从数据源获取数据,例如网络请求
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
//创建执行器,用于从本地缓存获取数据
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//根据当前机器参数计算需要设置的缓存大小
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
//创建 Bitmap 池,用于回收LruCache缓存的图片,把图片回收到bitmapPool中,这样下次再创建图片时,可服用该内存,避免连续创建回收内存,造成的内存抖动
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
//创建数组池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
//创建内存缓存
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
//创建磁盘缓存
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
//创建Engine,真正处理request的类,例如发起网络请求图片,从磁盘读取图片等
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//代码2 getRetriever() 返回的就是该对象
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
//创建Glide
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
上面代码跟注释我们可知,这里 builder 主要构建线程池、复用池、缓存策略、执行 Engine 。现在我们来到真正创建Glide的地方。
代码五 类Glide.java
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
boolean isLoggingRequestOriginsEnabled) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
final Resources resources = context.getResources();
registry = new Registry();
registry.register(new DefaultImageHeaderParser());
...省略若干代码,创建需要加入到registry 的类...
ContentResolver contentResolver = context.getContentResolver();
//添加各种Encoder(把数据存为File)、ResourceDecoder(把数据从类型A转为类型B)、
//ModelLoaderFactory(用于创建ModelLoader,它用于将任意复杂的数据模型转换为可由 DataFetcher 获取模型所代表的资源数据的具体数据类型。用来加载资源的。 )
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
...省略若干代码...
.append(Drawable.class, Drawable.class, new UnitDrawableDecoder())
/* Transcoders */
.register(
Bitmap.class,
BitmapDrawable.class,
new BitmapDrawableTranscoder(resources))
.register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
.register(
Drawable.class,
byte[].class,
new DrawableBytesTranscoder(
bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
.register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
//该工厂用于生产ImageViewTarget,最终通过ImageViewTarget对象把图片addView到界面上
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
}
可以看到,代码主要就是Registry 对象,调用append,register 函数设置一些参数。这些参数,主要作用就是对后面的图片解析、加载
分析append方法:
public <Model, Data> Registry append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
直接调用了ModeLoaderRegistry的append方法:
public synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.append(modelClass, dataClass, factory);
cache.clear();
}
在ModelLoaderRegistry中封装了了一个MultiModelLoaderFactory,MultiModelLoaderFactory里面有一个List,append进来的都最终放到了这个list中,cache只是为了提高效率缓存。具体看ModelLoaderRegistry和MultiModelLoaderFactory源码,关键方法进行了注释。
Registry的append方法没什么难度,这个是放进去,那么我们怎么取出来了呢?
这个就是Registry的getModelLoaders方法,根据Model类型来获取一个ModelLoader的List。可以看ModelLoaderRegistry的源码
package com.bumptech.glide.load.model;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pools.Pool;
import com.bumptech.glide.Registry.NoModelLoaderAvailableException;
import com.bumptech.glide.util.Synthetic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Maintains an ordered put of {@link ModelLoader}s and the model and data types they handle in
* order from highest priority to lowest.
*/
// Hides Model throughout.
@SuppressWarnings("TypeParameterHidesVisibleType")
public class ModelLoaderRegistry {
private final MultiModelLoaderFactory multiModelLoaderFactory;
private final ModelLoaderCache cache = new ModelLoaderCache();
public ModelLoaderRegistry(@NonNull Pool<List<Throwable>> throwableListPool) {
this(new MultiModelLoaderFactory(throwableListPool));
}
private ModelLoaderRegistry(@NonNull MultiModelLoaderFactory multiModelLoaderFactory) {
this.multiModelLoaderFactory = multiModelLoaderFactory;
}
public synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.append(modelClass, dataClass, factory);
cache.clear();
}
public synchronized <Model, Data> void prepend(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.prepend(modelClass, dataClass, factory);
cache.clear();
}
public synchronized <Model, Data> void remove(
@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {
tearDown(multiModelLoaderFactory.remove(modelClass, dataClass));
cache.clear();
}
public synchronized <Model, Data> void replace(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
tearDown(multiModelLoaderFactory.replace(modelClass, dataClass, factory));
cache.clear();
}
private <Model, Data> void tearDown(
@NonNull List<ModelLoaderFactory<? extends Model, ? extends Data>> factories) {
for (ModelLoaderFactory<? extends Model, ? extends Data> factory : factories) {
factory.teardown();
}
}
// We're allocating in a loop to avoid allocating empty lists that will never have anything added
// to them.
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
@NonNull
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
if (modelLoaders.isEmpty()) {
throw new NoModelLoaderAvailableException(model);
}
int size = modelLoaders.size();
boolean isEmpty = true;
List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
/*
*下面这条注释的意思
* https://stackoverflow.com/questions/17836373/what-does-noinspection-forloopreplaceablebyforeach-mean
*/
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0; i < size; i++) {
ModelLoader<A, ?> loader = modelLoaders.get(i);
if (loader.handles(model)) {
if (isEmpty) {
//这块做了一个小优化,初始化的时候就指定了大小,避免后期扩展的时候拷贝
filteredLoaders = new ArrayList<>(size - i);
isEmpty = false;
}
filteredLoaders.add(loader);
}
}
if (filteredLoaders.isEmpty()) {
throw new NoModelLoaderAvailableException(model, modelLoaders);
}
return filteredLoaders;
}
public synchronized <Model, Data> ModelLoader<Model, Data> build(
@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {
return multiModelLoaderFactory.build(modelClass, dataClass);
}
@NonNull
public synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {
return multiModelLoaderFactory.getDataClasses(modelClass);
}
@NonNull
private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
@NonNull Class<A> modelClass) {
//这块又用到了缓存思想,如果没有新的modelClass添加,cache中的就是需要的
//如果,不从缓存中取,就需要调用multiModelLoaderFactory的build,这样的化,就可能会实例化多个ModelLoader,开销会很大
List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
if (loaders == null) {
loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
cache.put(modelClass, loaders);
}
return loaders;
}
@NonNull
@SuppressWarnings("unchecked")
private static <A> Class<A> getClass(@NonNull A model) {
return (Class<A>) model.getClass();
}
private static class ModelLoaderCache {
private final Map<Class<?>, Entry<?>> cachedModelLoaders = new HashMap<>();
@Synthetic
ModelLoaderCache() {}
public void clear() {
cachedModelLoaders.clear();
}
public <Model> void put(Class<Model> modelClass, List<ModelLoader<Model, ?>> loaders) {
Entry<?> previous = cachedModelLoaders.put(modelClass, new Entry<>(loaders));
if (previous != null) {
throw new IllegalStateException("Already cached loaders for model: " + modelClass);
}
}
@Nullable
@SuppressWarnings("unchecked")
public <Model> List<ModelLoader<Model, ?>> get(Class<Model> modelClass) {
Entry<Model> entry = (Entry<Model>) cachedModelLoaders.get(modelClass);
return entry == null ? null : entry.loaders;
}
private static class Entry<Model> {
@Synthetic final List<ModelLoader<Model, ?>> loaders;
public Entry(List<ModelLoader<Model, ?>> loaders) {
this.loaders = loaders;
}
}
}
}
MultiModelLoaderFactory是一个很重要的类,首先它存储了所有了modelClass、dataClass和ModelLoaderFactory的信息,在entries List里面。还有两个很重要的重载方法load。
synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass)
根据modelClass类型,把所有entries List中的所有modelClass类型的ModelLoader都通过工厂类ModelLoaderFactory方法build出来,并放到loaders List中返回。
需要说明的是不同的ModelLoaderFactory的build实现是不同的,build方法中传入的MultiModelLoaderFactory对象。
3 RequestManager getRetriever(activity).get(activity);
这里的 get 也有很多重载的函数,我们就看 Activity 参数的重载。
public class RequestManagerRetriever implements Handler.Callback {
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
//如果在主线程中并且不为 Application 级别的 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) {
//一直到查找 BaseContext
return get(((ContextWrapper) context).getBaseContext());
}
}
//如果不在主线程中或为 Application 就直接执行
return getApplicationManager(context);
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
....
}
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
....
}
//通过 Activity 拿到 RequestManager
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull Activity activity) {
//判断当前是否在子线程中请求任务
if (Util.isOnBackgroundThread()) {
//通过 Application 级别的 Context 加载
return get(activity.getApplicationContext());
} else {
//检查 Activity 是否已经销毁
assertNotDestroyed(activity);
//拿到当前 Activity 的 FragmentManager
android.app.FragmentManager fm = activity.getFragmentManager();
//主要是生成一个 Fragment 然后绑定一个请求管理 RequestManager
return fragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
}
下面我们看下 fragmentGet 函数实现
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//1. 在当前的 Acitivty 添加一个 Fragment 用于管理请求的生命周期
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//拿到当前请求的管理类
RequestManager requestManager = current.getRequestManager();
//如果不存在,则创建一个请求管理者保持在当前管理生命周期的 Fragment 中,相当于 2 者进行绑定,避免内存泄漏。
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
//返回当前请求的管理者
return requestManager;
}
通过上面的代码可知,这里用于 Fragment 管理请求的生命周期,那么我们具体来看看 Fragment 怎么添加到 Activity 中。
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//通过 TAG 拿到已经实例化过的 Fragment ,相当于如果同一个 Activity Glide.with..多次,那么就没有必要创建多个。
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//如果在当前 Activity 中没有拿到管理请求生命周期的 Fragment ,那么就从缓存中看有没有
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
//如果缓存也没有得,就直接实例化一个 Fragment
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
//如果已经有执行的请求就开始
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
//添加到 Map 缓存中
pendingRequestManagerFragments.put(fm, current);
//通过当前 Activity 的 FragmentManager 开始提交添加一个 Fragment 容器
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//添加到 FragmentManager 成功,发送清理缓存。
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
最后就到了 把请求管理类绑定到 Fragment 中。
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
...
//如果不存在,则创建一个请求管理者保持在当前管理生命周期的 Fragment 中,相当于 2 者进行绑定,避免内存泄漏。
if (requestManager == null) {
//拿到单例 Glide
Glide glide = Glide.get(context);
//构建请求管理,current.getGlideLifecycle(),就是 ActivityFragmentLifecycle 后面我们会讲到这个类
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//将构建出来的请求管理绑定在 Fragment 中。
current.setRequestManager(requestManager);
}
//返回当前请求的管理者
return requestManager;
}
看下怎么构建请求管理类的
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
//实例化
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
public RequestManager(
@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),
glide.getConnectivityMonitorFactory(),
context);
}
// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
//这里只要是添加生命周期监听,Fragment 传递过来的
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
//添加网络变化的监听
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
到这里请求管理类 RequestManager + Fragment 已经绑定成功了,声明周期监听也设置了。
那他们相互是怎么保证生命周期的传递勒,我们主要看 Fragment 生命周期方法
//这里为什么监控 Fragment 的生命周期勒,其实大家应该也知道 Fragment 是依附在 Activity 的 Activity 的生命周期在 Fragment 中都有,所以监听 Fragment 就行了。
public class RequestManagerFragment extends Fragment {
//相当于生命周期回调
private final ActivityFragmentLifecycle 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();
}
...
}
这里的 lifecycle 负责生命周期的处理,我们在深入看看去
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}
}
这里知道了吧,它实现的是 Glide 中的 Lifecycle 生命周期接口,注册是在刚刚我们讲解 RequestManagerFactory 工厂中实例化的 RequestManager 然后在构造函数中添加了生命周期回调监听,具体来看下。
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
...
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
...
}
二 load
load 函数加载相对于比较简单。我们看下具体代码实现
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
.....
public RequestBuilder<Drawable> load(@Nullable String string) {
//这里调用 Drawable 图片加载请求器为其加载
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable File file) {
return asDrawable().load(file);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
}
可以看到 load 也有很多重载的函数,不得不说是真的很强大啊,只要给一个图片资源那么就能给你加载出来。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
// 描述加载的数据源-这里可以看做是我们刚刚传递进来的 http://xxxx.png
@Nullable private Object model;
// 描述这个请求是否已经添加了加载的数据源
private boolean isModelSet;
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
}
好的, 到这里 RequestBuilder 就构建好了, 接下来就等待执行这个请求了, 我们看看它的 RequestBuilder 的 into 方法。
三 into
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
//根据ImageView 的ScaleType 类型,进行参数设置,注意这里是clone 一个新的对象,在新对象上操作的
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
1
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
//因为前面调用asDrawable ,所以会创建这个ViewTarget
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
如上步骤通过 ImageViewTargetFactory 创建 BitmapImageViewTarget 和DrawableImageViewTarget 。
先拿到当前 ImageView getScaleType 类型的属性,然后重新 clone 一个进行配置;调用 into 重载继续构建
回到1 处
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
//调用过load 函数,这个变量是true
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//创建请求,用于显示图片。图片有可能是从缓存中,也有可能是从网络获取
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//获取该目标 对应的request,和当前的request进行比较
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
//把当前的request,设置到target(ViewTarget)
target.setRequest(request);
//2 进行图片请求操作
requestManager.track(target, request);
return target;
}
- 为 target buildRequest 构建一个 Glide request 请求;
- 将构建出来的 Request 交于 RequestManager 来执行.
现在看 request 创建出来的操作
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
Request errorRequest =
errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
//取出缩略图的配置,优先级,,缩略图的宽高等
Priority thumbPriority = thumbnailBuilder.isPrioritySet()
? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
//使用缩略图的参数,创建一个Request
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
//因为调用.thumbnail 传递GlideRequest 参数时,这个请求也可能设置了缩略图和错误图(也就是缩略图的缩略图),所以这里进行递归创建Request
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
}
... 下面省略若干代码,是根据其他情况,创建Request ...
}
继续跟踪
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
最后我们发现是 SingleRequest.obtain
来为我们构建的 Request 请求对象,开始只是初始化一些配置属性,下面我们就来找最开始 标注2的地方, 先来看下 track
函数执行。
//这里对当前 class 加了一个同步锁避免线程引起的安全性
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
//添加一个目标任务
targetTracker.track(target);
//执行 Glide request
requestTracker.runRequest(request);
}
public void runRequest(@NonNull Request request) {
//添加一个请求
requests.add(request);
//是否暂停
if (!isPaused) {
//没有暂停,开始调用 Request begin 执行
request.begin();
} else {
//如果调用了 暂停,清理请求
request.clear();
pendingRequests.add(request);
}
}
上面的逻辑是先为 requests
添加一个请求,看看是否是停止状态,如果不是就调用 request.begin();
执行。
这里的 Request
是一个接口,通过之前我们讲到 buildRequest
函数可知 Request
的实现类是 SingleRequest
我们就直接看它的 begin
函数.
public synchronized void begin() {
...
if (model == null) {
...
// model(url)为空,回调加载失败
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
// If we're restarted after we're complete (usually via something like a notifyDataSetChanged
// that starts an identical request into the same Target or View), we can simply use the
// resource and size we retrieved the last time around and skip obtaining a new size, starting a
// new load etc. This does mean that users who want to restart a load because they expect that
// the view size has changed will need to explicitly clear the View or Target before starting
// the new load.
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
// Restarts for requests that are neither complete nor running can be treated as new requests
// and can run again from the beginning.
status = Status.WAITING_FOR_SIZE;
//glide 会根据显示图片的宽高进行缓存,所以这里需要获得View的宽高,overrideWidth,overrideHeight默认为-1
//所以第一次会到else分支,获取View的宽高
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 当使用override() API为图片指定了一个固定的宽高时直接执行onSizeReady,
// 最终的核心处理位于onSizeReady
onSizeReady(overrideWidth, overrideHeight);
} else {
// 根据imageView的宽高算出图片的宽高,最终也会走到onSizeReady
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
// 预先加载设置的缩略图
target.onLoadStarted(getPlaceholderDrawable());
}
}
我们接着往下看 onSizeReady
public synchronized void onSizeReady(int width, int height) {
if (status != Status.WAITING_FOR_SIZE) {
return;
}
//设置状态为正在请求
status = Status.RUNNING;
//设置宽高
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
//这里的engine 是在创建Glide的时候,build() 创建的,engine封装了各种Executor,内存缓存等
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
// This is a hack that's only useful for testing right now where loads complete synchronously
// even though under any executor running on any thread but the main thread, the load would
// have completed asynchronously.
if (status != Status.RUNNING) {
loadStatus = null;
}
}
接着再看load
public synchronized <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor) {
//拿到缓存或者请求的 key
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//根据 key 拿到活动缓存中的资源
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
//如果 ActiveResources 活动缓存中有就回调出去
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
return null;
}
//尝试从 LruResourceCache 中找寻这个资源
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
//如果内存缓存 Lru 中资源存在回调出去
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
return null;
}
//------------- 走到这里说明活动缓存 跟内存 缓存都没有找到 -----------
//根据 Key 看看缓存中是否正在执行
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
//如果正在执行,把数据回调出去
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// -------------- 走到这里说明是一个新的任务 ---------------
// -------------- 构建新的请求任务 ---------------
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//把当前需要执行的 key 添加进缓存
jobs.put(key, engineJob);
//执行任务的回调
engineJob.addCallback(cb, callbackExecutor);
//开始执行。
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
通过 engine.load
这个函数里面的逻辑,我们可以总结几点:
- 先构建请求或者缓存 KEY ;
- 根据 KEY 从内存缓存中查找对应的资源数据(ActiveResources(活动缓存,内部是一个 Map 用弱引用持有),LruResourceCache),如果有就回调 对应监听的 onResourceReady 表示数据准备好了。
- 从执行缓存中查找对应 key 的任务
- 如果找到了,就说明已经正在执行了,不用重复执行。
- 没有找到,通过 EngineJob.start 开启一个新的请求任务执行。
接着往下看
engine .start
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
//若能从磁盘缓存获取数据,就使用diskCacheExecutor
//否则在根据其他的条件判断使用哪个Executor
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
boolean willDecodeFromCache() {
//先看下面的getNextStage 分析
Stage firstStage = getNextStage(Stage.INITIALIZE);
//那这里就很明了了,如果可以从磁盘缓存读取,就返回true
return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
}
接着往下看 get NextState 获取下一个阶段,应该从哪里获取数据
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
//当前是初始阶段,则看磁盘缓存策略,是否可以在磁盘中获取资源缓存(也就是解析后的缓存)
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
//当前是资源缓存,看下一步能不能从磁盘缓存中获取源数据缓存
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// Skip loading from source if the user opted to only retrieve the resource from cache.
//当前是数据缓存,下一步能不能从源数据处获取数据,例如从服务器获取
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
下面我们就来看下 engineJob.start
具体执行逻辑:
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
//拿到 Glide 执行的线程池
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
//开始执行
executor.execute(decodeJob);
}
我们这里看到 GlideExecutor 线程池 实现run 的方法
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
//线程执行调用 run
@Override
public void run() {
GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
DataFetcher<?> localFetcher = currentFetcher;
try {
//是否取消了当前请求
if (isCancelled) {
notifyFailed();
return;
}
//执行
runWrapped();
} catch (CallbackException e) {
.....//一些错误回调
}
}
接着看 runWrapped
/**
* 初始化之后第一次运行时 runReason 为 INITIALIZE
*/
private void runWrapped() {
runWrappedCount++;
switch (runReason) {
case INITIALIZE:
//获取下一阶段的状态
stage = getNextStage(Stage.INITIALIZE);
//根据下一阶段状态,判断具体有哪个类执行
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
//从磁盘缓存获取资源数据
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
//从磁盘缓存获取源数据
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
//从数据源获取数据,例如 从服务器获取数据
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
//这里执行当前的Generator,进第11步
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
// Otherwise a generator started a new load and we expect to be called back in
// onDataFetcherReady.
}
currentGenerator.startNext()
这里的currentGenerator 是SourceGenerator
接着 往下看。SourceGenerator startNext
@Override
public boolean startNext() {
//第一次 从源数据获取数据时,是不会执行到这里的
//从下面的分析可知,等下次有数据时,也会调用到这里,就把数据缓存到磁盘
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
//放入缓存
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
//helper.getLoadData() 获取所有符合条件的ModelLoader,这些ModelLoader 包括默认的和自定义的
// 这里的符合条件,也就是ModelLoader 中的handles函数是否返回true,再说直白点,就是判断在load()传入的对象类型,是否可以被ModelLoader所处理
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
//3 通过LoadData对象内部的 fetcher ,来进行实际的请求操作(例如发起网络请求)
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
//获取已注册的加载器中所有可以加载当前模型的加载器
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
//每一个ModeLoader 都有一个内部类LoadData,通过函数buildLoadData 来创建
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
现在接着看 glideContext.getRegistry().getModelLoaders(model); 这里通过getRegistry() 得到 Registry。 接着下来看如何获取LoadData。
查看 Registry 中的方法 getModelLoaders
@NonNull
public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {
List<ModelLoader<Model, ?>> result = modelLoaderRegistry.getModelLoaders(model);
if (result.isEmpty()) {
throw new NoModelLoaderAvailableException(model);
}
return result;
}
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
int size = modelLoaders.size();
boolean isEmpty = true;
List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
for (int i = 0; i < size; i++) {
ModelLoader<A, ?> loader = modelLoaders.get(i);
//通过 ModelLoader#handles 方法判断加载器是否可以处理当前类型的数据(这个数据时通过load 传递进来的),返回所有可以处理的加载器
if (loader.handles(model)) {
if (isEmpty) {
filteredLoaders = new ArrayList<>(size - i);
isEmpty = false;
}
filteredLoaders.add(loader);
}
}
return filteredLoaders;
}
这里的 modelLoader 有一个类型是StringLoader ,StringLoader.buildLoadData->MultiModelLoader.buildLoadData
@Override
public LoadData<Data> buildLoadData(
@NonNull Model model, int width, int height, @NonNull Options options) {
Key sourceKey = null;
int size = modelLoaders.size();
List<DataFetcher<Data>> fetchers = new ArrayList<>(size);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0; i < size; i++) {
//这里的modelLoaders,是在创建MultiModelLoader的时候赋值的
ModelLoader<Model, Data> modelLoader = modelLoaders.get(i);
//在这里有进行了一次过滤,在更小的范围内查找,可以处理model的ModelLoader。(这次是在StringLoader 中查找,可以处理URL的ModelLoader)
if (modelLoader.handles(model)) {
LoadData<Data> loadData = modelLoader.buildLoadData(model, width, height, options);
if (loadData != null) {
//这里把LoadData的值提取出来,
sourceKey = loadData.sourceKey;
//以本例子,这里的fetcher 是HttpUrlFetcher
fetchers.add(loadData.fetcher);
}
}
}
return !fetchers.isEmpty() && sourceKey != null
? new LoadData<>(sourceKey, new MultiFetcher<>(fetchers, exceptionListPool))
: null;
}
获取LoadData后 回到startNext ,标注3位置,来到loadData.fetcher.loadData(helper.getPriority(), this); 这里的fetcher 是 HttpUrlFetcher
,我们现在来看 loadData的实现
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//http 请求,返回一个 InputStream 输入流
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//将 InputStream 以回调形式回调出去
callback.onDataReady(result);
} catch (IOException e) {
callback.onLoadFailed(e);
} finally {
...
}
}
我们继续看 loadDataWithRedirects
这个函数是怎么生成的一个 InputStream
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new HttpException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.connect();
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
return getStreamForSuccessfulRequest(urlConnection);
}
...//抛的异常我们暂时先不管
}
现在看到Http 请求了,这里是 HttpURLConnection 作为 Glide 底层成网络请求的。请求成功之后直接返回的是一个输入流,最后会通过 onDataReady
回调到 DecodeJob onDataFetcherReady 函数,我们跟下回掉回到 SourceGenerator 中
@Override
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
//调用DecodeJob的reschedule,用线程池执行任务,实际上就是再次调用SourceGenerator的startNext
cb.reschedule();
} else {
// 又是一个回调函数
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
这里会有 else 因为我们没有配置缓存,继续回调。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
...
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey; //当前返回数据的 key
this.currentData = data; //返回的数据
this.currentFetcher = fetcher; //返回的数据执行器,这里可以理解为 HttpUrlFetcher
this.currentDataSource = dataSource; //数据来源 url
this.currentAttemptingKey = attemptedKey;
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
//4 解析返回回来的数据
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
...
}
//解析返回的数据
private void decodeFromRetrievedData() {
Resource<R> resource = null;
try {
// 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream , currentDataSource
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
//解析完成后,通知下去
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
续跟 decodeFromData 看看怎么解析成 Resource 的
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
//继续解析数据
Resource<R> result = decodeFromFetcher(data, dataSource);
return result;
} finally {
fetcher.cleanup();
}
}
//这里的data 是一个泛型,本例中是 Stream 流,从http请求获取到的
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
//获取一个LoadPath,它是根据数据类型(这里是stream),ResourceDecoder(资源解码),transcoder(资源转码)
//从这些参数可以看出,最终把数据流转为Bitmap 或Drawable ,就是在LoadPath中进行的,这里是指DecodePath
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
return runLoadPath(data, dataSource, path);
}
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
LoadPath<Data, ResourceType, R> path) throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
//执行LoadPath 的load ,进行解码,转换操作
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
上面代码看到,为了解析数据首先构建一个 LoadPath, 然后创建一个 InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作放到了 LoadPath.load 方法中 ,接下来看下 LoadPath.load 方法的具体逻辑操作:
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
//重点在这里,调用LoadPath 的decode 解码
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
跟 path.decode
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
//调用 decodeResourec 将数据解析成中间资源
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
//解析完数据回调出去
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
//转换资源为目标资源
return transcoder.transcode(transformed, options);
}
@NonNull
private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options) throws GlideException {
...
try {
return decodeResourceWithList(rewinder, width, height, options, exceptions);
} finally {
...
}
}
@NonNull
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
// 调用 ResourceDecoder.decode 解析数据
result = decoder.decode(data, width, height, options);
}
} catch (IOException | RuntimeException | OutOfMemoryError e) {
...
}
return result;
}
decode是一个ResourceDecoder接口(资源解码器),根据不同的DataType和ResourceType它会有不同的实现类,这里的实现类是ByteBufferBitmapDecoder,下面看看它的decode 流程
public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
@NonNull Options options)
throws IOException {
InputStream is = ByteBufferUtil.toStream(source);
return downsampler.decode(is, width, height, options);
}
downsampler主要是对流进行解码,旋转,压缩,圆角等处理 ,
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
Options options, DecodeCallbacks callbacks) throws IOException {
byte[] bytesForOptions = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
BitmapFactory.Options bitmapFactoryOptions = getDefaultOptions();
bitmapFactoryOptions.inTempStorage = bytesForOptions;
DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
DownsampleStrategy downsampleStrategy = options.get(DownsampleStrategy.OPTION);
boolean fixBitmapToRequestedDimensions = options.get(FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS);
boolean isHardwareConfigAllowed =
options.get(ALLOW_HARDWARE_CONFIG) != null && options.get(ALLOW_HARDWARE_CONFIG);
try {
//解析得到bitmap
Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
requestedHeight, fixBitmapToRequestedDimensions, callbacks);
//把bitmap 封装进Resource ,返回Resource 对象
return BitmapResource.obtain(result, bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
byteArrayPool.put(bytesForOptions);
}
}
private Bitmap decodeFromWrappedStreams(
ImageReader imageReader,
BitmapFactory.Options options,
DownsampleStrategy downsampleStrategy,
DecodeFormat decodeFormat,
PreferredColorSpace preferredColorSpace,
boolean isHardwareConfigAllowed,
int requestedWidth,
int requestedHeight,
boolean fixBitmapToRequestedDimensions,
DecodeCallbacks callbacks)
throws IOException {
long startTime = LogTime.getLogTime();
int[] sourceDimensions = getDimensions(imageReader, options, callbacks, bitmapPool);
int sourceWidth = sourceDimensions[0];
int sourceHeight = sourceDimensions[1];
String sourceMimeType = options.outMimeType;
// If we failed to obtain the image dimensions, we may end up with an incorrectly sized Bitmap,
// so we want to use a mutable Bitmap type. One way this can happen is if the image header is so
// large (10mb+) that our attempt to use inJustDecodeBounds fails and we're forced to decode the
// full size image.
if (sourceWidth == -1 || sourceHeight == -1) {
isHardwareConfigAllowed = false;
}
int orientation = imageReader.getImageOrientation();
int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation);
boolean isExifOrientationRequired = TransformationUtils.isExifOrientationRequired(orientation);
int targetWidth =
requestedWidth == Target.SIZE_ORIGINAL
? (isRotationRequired(degreesToRotate) ? sourceHeight : sourceWidth)
: requestedWidth;
int targetHeight =
requestedHeight == Target.SIZE_ORIGINAL
? (isRotationRequired(degreesToRotate) ? sourceWidth : sourceHeight)
: requestedHeight;
ImageType imageType = imageReader.getImageType();
//计算缩放比例,结果会体现在options参数中
calculateScaling(
imageType,
imageReader,
callbacks,
bitmapPool,
downsampleStrategy,
degreesToRotate,
sourceWidth,
sourceHeight,
targetWidth,
targetHeight,
options);
calculateConfig(
imageReader,
decodeFormat,
isHardwareConfigAllowed,
isExifOrientationRequired,
options,
targetWidth,
targetHeight);
//计算sdk版本是否大于KITKAT,在该系统及之前 图片复用仅支持大小相同的位图
boolean isKitKatOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
//下面的判断,来计算是否在BitmapPool中 是否有bitmap可以被复用,如果有就把bitmap 设置到options.inBitmap
//这样在根据options 去解析生成bitmap的时候,就不需要再次分配内存了,避免了内存抖动
// Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding.
if ((options.inSampleSize == 1 || isKitKatOrGreater) && shouldUsePool(imageType)) {
int expectedWidth;
int expectedHeight;
if (sourceWidth >= 0
&& sourceHeight >= 0
&& fixBitmapToRequestedDimensions
&& isKitKatOrGreater) {
expectedWidth = targetWidth;
expectedHeight = targetHeight;
} else {
float densityMultiplier =
isScaling(options) ? (float) options.inTargetDensity / options.inDensity : 1f;
int sampleSize = options.inSampleSize;
int downsampledWidth = (int) Math.ceil(sourceWidth / (float) sampleSize);
int downsampledHeight = (int) Math.ceil(sourceHeight / (float) sampleSize);
expectedWidth = Math.round(downsampledWidth * densityMultiplier);
expectedHeight = Math.round(downsampledHeight * densityMultiplier);
}
// If this isn't an image, or BitmapFactory was unable to parse the size, width and height
// will be -1 here.
if (expectedWidth > 0 && expectedHeight > 0) {
//该函数会在bitmapPool中查找符合大小的bitmap ,如果找到了就设置给inBitmap
setInBitmap(options, bitmapPool, expectedWidth, expectedHeight);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
boolean isP3Eligible =
preferredColorSpace == PreferredColorSpace.DISPLAY_P3
&& options.outColorSpace != null
&& options.outColorSpace.isWideGamut();
options.inPreferredColorSpace =
ColorSpace.get(isP3Eligible ? ColorSpace.Named.DISPLAY_P3 : ColorSpace.Named.SRGB);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
options.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
}
//根据options 把流解析为Bitmap
Bitmap downsampled = decodeStream(imageReader, options, callbacks, bitmapPool);
callbacks.onDecodeComplete(bitmapPool, downsampled);
Bitmap rotated = null;
if (downsampled != null) {
// If we scaled, the Bitmap density will be our inTargetDensity. Here we correct it back to
// the expected density dpi.
downsampled.setDensity(displayMetrics.densityDpi);
rotated = TransformationUtils.rotateImageExif(bitmapPool, downsampled, orientation);
if (!downsampled.equals(rotated)) {
bitmapPool.put(downsampled);
}
}
return rotated;
}
至此已经得到了解析后的资源了,接下来就是要显示到指定的ImageView控件上
回到上述方法中注释处4 Decodejob notifyEncodeAndRelease(resource, currentDataSource);
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
// 通知主线程回调,加载图片
notifyComplete(result, dataSource);
// 更新状态为编码
stage = Stage.ENCODE;
try {
//是否可以将转换的图片缓存
if (deferredEncodeManager.hasResourceToEncode()) {
//磁盘缓存入口
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// Call onEncodeComplete outside the finally block so that it's not called if the encode process
// throws.
onEncodeComplete();
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
// 这个callback 就是 EngineJob对象, 是在创建Decodejob的时候,传递进来,第本节 第9步
callback.onResourceReady(resource, dataSource);
}
我们直接看 EngineJob 的 onResourceReady 回调函数
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
@Synthetic
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
resource.recycle();
release();
return;
} else if (cbs.isEmpty()) {
...
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
//回调上层 Engine 任务完成了
listener.onEngineJobComplete(this, localKey, localResource);
//遍历资源回调给 ImageViewTarget
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
通过上面 EngineJob 的 onResourceReady 回调函数 主要做了 2 件事儿
- 通知上层任务完成。
- 回调 ImageViewTarget 用于展示数据。
我们看下 listener.onEngineJobComplete 具体实现
@SuppressWarnings("unchecked")
@Override
public synchronized void onEngineJobComplete(
EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
if (resource != null) {
resource.setResourceListener(key, this);
//收到下游返回回来的资源,添加到活动缓存中
if (resource.isCacheable()) {
activeResources.activate(key, resource);
}
}
jobs.removeIfCurrent(key, engineJob);
}
后通知 ImageViewTarget ,我们看EngineJob 方法中 遍历资源回调给 ImageViewTarget 中的操作
//遍历资源回调给 ImageViewTarget
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
private class CallResourceReady implements Runnable {
private final ResourceCallback cb;
CallResourceReady(ResourceCallback cb) {
this.cb = cb;
}
@Override
public void run() {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
...
//返回准备好的资源
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
最后我们继续跟 callCallbackOnResourceReady
@Synthetic
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
try {
//回调给 SingleRequest
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
最后看下 SingleRequest onResourceReady 回调
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
loadStatus = null;
....
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
releaseResource(resource);
...
onLoadFailed(exception);
return;
}
if (!canSetResource()) {
releaseResource(resource);
status = Status.COMPLETE;
return;
}
//当资源准备好的时候
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
...
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
//回调给目标 ImageViewTarget 资源准备好了
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
//加载成功
notifyLoadSuccess();
}
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
...
private void setResourceInternal(@Nullable Z resource) {
//调用 setResource 函数,将资源显示出来
setResource(resource);
...
}
}
这里ImageViewTarget 的实现类中 BitmapImageViewTarget 和 DrawableImageViewTarget 中具体显示方法如下
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
// Public API.
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
@SuppressWarnings("WeakerAccess")
public BitmapImageViewTarget(ImageView view) {
super(view);
}
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public BitmapImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
@Override
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
}
通过 setResouse 方法 把图片信息显示出来。
至此,Glide 源码就大致分析完了
总结
总的来说,图片加载流程大致可分为 4 步:
- 准备工作
- 内存缓存
- 数据加载
- 解码显示
准备工作包括:
- 添加一个 Fragment 到对应的 Activity/Fragment 上面,监听生命周期。以控制请求的暂停执行、恢复执行,或清理资源
- 递归构建 Request。以协调主图、缩略图、出错图的加载请求。缩略图和主图同时加载,如果主图先加载完成,则取消缩略图的加载请求,否则先显示缩略图,等主图加载完成后再清除。出错图则是在主图加载失败后才开始加载并显示
- 获取目标尺寸。以 ImageView 为例,尺寸是在 ViewTreeObserver 的 onPreDraw 方法回调后获取的。
- 设置占位图。占位图是直接调用 setImageDrawable 方法设置的,因此不需要和主图协调
内存缓存包括两部分:
- 活跃的资源,即加载完成后已回调给 Target 并且未被释放的资源,可以简单理解为正在显示的图片,通过引用计数判断具体释放的时机
- 内存缓存,即不再显示,但仍处于内存中未被 LRU 算法移除的资源
数据加载包括两部分:
- 从磁盘缓存中加载
- 从目标地址中加载
磁盘缓存又分为两部分:
- 从缩放、变换后的文件缓存中查找
- 如果找不到,再到原始的图片缓存中查找
目标地址有很多种,比如本地文件路径、文件句柄、Asset、服务器链接等。
成功获取到数据之后:
- 首先需要将原始图像数据缓存到本地磁盘中
- 接着将数据解码为 Bitmap/Drawable 等资源类型,同时应用圆角等变换效果(如果不是从变换后的文件缓存中获取的话)
- 然后才能回调给 Target 并显示
- 最后还需要将缩放、变换后的图片数据写入到磁盘缓存,并清理资源
Target 显示图片时还会判断是否需要执行过渡动画,如果需要,则执行过渡动画后再显示资源。显示资源时,会判断该资源类型是否为 gif 图,如果是,则开始执行动画,否则直接显示即可。