Glide内部HTTP通讯组件的底层实现是基于HttpUrlConnection来进行定制的。但是HttpUrlConnection的可扩展性比较有限,因此我们今天介绍如何将Glide中的HTTP通讯组件替换成OkHttp。
一、前言
在Glide v3
中,当我们创建好一个自定义模块之后,还必须在AndroidManifest.xml文件中注册它才能生效。随着Glide框架的不断优化,在Glide v4
中我们只需要使用@GlideModule
这个注解就能够让Glide轻轻松松识别到我们创建的自定义模块。
Glide已经更新到4.9.0,本文就不去介绍Glide v3中的自定义模块,只介绍Glide v4中如何自定义模块。当然如果感兴趣的话也可以学习一下旧版本中的自定义模块,推荐一篇非常优秀的文章。
二、自定义模块基本使用
Glide v4是使用注解机制来完成自定义模块的创建工作的,因此在工作正式开始之前我们还需要引入一些必需的依赖库。
1、添加对 Glide 的注解解析器的依赖和对OkHttp集成库的依赖
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.8.0'
2、创建自定义模块
从Glide v4开始,Glide框架引入了注解机制,自定义模块的创建也变得非常简单。
- 首先要实现AppGlideModule 类。
- 接着给上述实现添加@GlideModule注解。
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
}
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
}
}
- 最后,你应该在你的 proguard.cfg 中 keep 住你的 AppGlideModule 实现。
-keep public class extends com.bumptech.glide.module.AppGlideModule
-keep class com.bumptech.glide.GeneratedAppGlideModuleImpl
这样模块类就创建完成了。我们可以看到上述代码中有两个需要重写的方法applyOptions和registerComponents,那么这两个方法的作用是什么呢?
applyOptions
认真阅读过上一篇文章的同学对applyOptions()
这个方法应该比较熟悉了,它在应用程序选项一节中多次出现过,它的主要职责就是配置对大部分应用程序合理的默认选项。
假如有这样一个场景:我希望Glide在加载图片的时候禁止任何缓存操作。为了满足这个条件,那么我应用中的图片加载语句可能是类似下面这样的:
Glide.with(this)
.asDrawable()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.load(IMAGE_URL)
.into(imageView);
一直重复编写这么长的语句显然是不理智的,此时我们就可以在applyOptions方法中配置所有请求的默认选项:
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
RequestOptions requestOptions = new RequestOptions()
.skipMemoryCache(true) //不使用内存缓存
.diskCacheStrategy(DiskCacheStrategy.NONE); //原图和缩略图都不进行磁盘缓存
builder.setDefaultRequestOptions(requestOptions);
}
这样所有的图片加载请求在默认情况下就不会进行缓存操作了,我们的图片加载语句也会变得很简单:
Glide.with(this)
.load(IMAGE_URL)
.into(imageView);
registerComponents
registerComponents
,顾名思义,这个方法的作用就是注册组件,这也是这一篇文章要介绍的重点内容。
假如有一天产品经理提出了一个新功能,需要显示图片的加载进度,由于Glide内部是基于HttpUrlConnection实现网络通讯的,我们在它的基础之上无法实现监听下载进度的功能,因此我们就需要用OkHttp替换HttpUrlConnection。
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new ProgressInterceptor()); //拦截器
OkHttpClient okHttpClient = builder.build();
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));
}
这样我们就成功地用OkHttp
替换掉HttpUrlConnection
来进行网络通讯。
在Registry
类中不仅定义了replace()
方法,还有prepend()
和append()
方法,它们可以用于设置 Glide 尝试每个ModelLoader
和ResourceDecoder
之间的顺序,我们可以根据实际需求选用。
-
prepend()
假如你的 ModelLoader
或者 ResourceDecoder
在某个地方失败了,这时候你想将已有的数据交由 Glide 的默认行为来处理,可以使用 prepend()
。 prepend()
将确保你的 ModelLoader
或 ResourceDecoder
先于之前注册的其他组件并被首先执行。如果你的 ModelLoader
或者 ResourceDecoder
从其 handles()
方法中返回了一个 false
或失败,所有其他的 ModelLoader
或 ResourceDecoder
将以它们被注册的顺序执行,一次一个,作为一种回退方案。
-
append()
要处理新的数据类型或提供一个到 Glide 默认行为的回退,使用 append()
。append()
将确保你的 ModelLoader
或 ResourceDecoder
仅在 Glide 的默认组件被尝试后才会被调用。 如果你正在尝试处理 Glide 的默认组件能处理的某些子类型 (例如一些特定的 Uri 授权或子类型),你可能需要使用 prepend()
来确保 Glide 的默认组件不会在你的定制组件之前加载。
-
replace()
要完全替换 Glide 的默认行为并确保它绝不运行,请使用 replace()
。 replace()
将移除所有处理给定模型和数据类的 ModelLoaders
,并添加你的 ModelLoader
来代替。 replace()
在使用库(例如 OkHttp 或 Volley)替换掉 Glide 的网络逻辑时尤其有用,这种时候你会希望确保仅 OkHttp 或 Volley 被调用。
参考链接
- Android图片加载框架最全解析(六),探究Glide的自定义模块功能
- http://bumptech.github.io/glide/