之前在做一个视频播放器项目时,由于该项目的时间比较长,代码也是经过了很多人手。这个项目的重点之一就是图片的加载。每个人对图片加载框架的喜好以及熟悉程度都不一样,导致了该项目里面有好几个ImageLoader。这样对系统资源是一个很大的浪费,维护起来也很麻烦。 接手之后第一件事就是统一图片加载框架。图片加载框架比较火的有Glide、Fresco和Picasso。试过用Fresco去加载一个几十张图片的ListView,虽然很快,但是内存抖动非常厉害。再用Glide实现同样的功能 ,内存的曲线很平滑。Picasso这个框架我了解的比较少,由于我有加载Gif图的需求,这是Picasso无法实现的,因此最终选用了Glide作为我的图片框架。
接下来的几篇文章将会对Glide的源码做一个分析总结。
- Android-Glide源码解析(一)调用流程
- Android-Glide源码解析(二)线程管理
- Android-Glide源码解析(三)图片处理
- 本系列文章基于Glide v4.8.0
Glide的使用方法如下
// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
Glide.with(this)调用了下面的方法。返回的是一个RequestManager对象。
//Glide.java
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
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的时候会先去获取Glide的实例。如果还没有初始化,则会对Glide初始化。
return Glide.get(context).getRequestManagerRetriever();
}
/**
* Get the singleton.
*
* @return the singleton
*/
@NonNull
public static Glide get(@NonNull Context context) {
//单例模式
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
/**初始化Glide的方法*/
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
//获取GlideModule注解
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
//解析AndroidManifest文件,查看是否设置了GlideModule。
//这个ManifestParser已经标记为过时了。新版的Glide不需要在Manifest文件里面设置。
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
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();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
//如果存在自定义的GlideModule,加载自定义配置
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//使用建造者模式,创建Glide实例
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
@NonNull
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();//内存缓存的Size计算器。里面包括计算Bitmap的缓存池大小,解码图片时的缓存数组大小等
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();//检查是否有网络权限
}
//创建bitmap池子
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);//磁盘缓存工厂对象
}
if (engine == null) {//负责管理加载操作、内存和缓存资源的对象
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
//RequestManager的管理器。Glide.with()方法就是通过这个类拿到了RequstManager对象。
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
分析完了Glide.with()方法,我们再来看下load()方法做了什么工作。
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(String)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
//这个asDrawable方法表示最终这张图片要加载到的目标是一个drawable里面。
return asDrawable().load(string);
}
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
//这个RequestBuilder是一个设置加载图片选项和启动加载的类。
return new RequestBuilder<>(glide, this, resourceClass, context);
}
@Override
public RequestBuilder<TranscodeType> load(@Nullable Object model) {
return loadGeneric(model);
}
/**asDrawable().load()方法最终执行到这里,返回一个ReuqestBuilder对象*/
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
接下来就到了Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
的into方法了。into是RequestBuilder的一个方法。
/**
* 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 RequestManager#clear(Target)
*
* @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}.
*/
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();//确保是在主线程里面调用的,如