Android 图片加载(四)Glide自定义模块

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框架引入了注解机制,自定义模块的创建也变得非常简单。

  1. 首先要实现AppGlideModule 类。
  2. 接着给上述实现添加@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) {
        
    }
}
  1. 最后,你应该在你的 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 尝试每个ModelLoaderResourceDecoder之间的顺序,我们可以根据实际需求选用。

假如你的 ModelLoader 或者 ResourceDecoder 在某个地方失败了,这时候你想将已有的数据交由 Glide 的默认行为来处理,可以使用 prepend()prepend() 将确保你的 ModelLoaderResourceDecoder 先于之前注册的其他组件并被首先执行。如果你的 ModelLoader 或者 ResourceDecoder 从其 handles() 方法中返回了一个 false 或失败,所有其他的 ModelLoaderResourceDecoder 将以它们被注册的顺序执行,一次一个,作为一种回退方案。

要处理新的数据类型或提供一个到 Glide 默认行为的回退,使用 append()append() 将确保你的 ModelLoaderResourceDecoder 仅在 Glide 的默认组件被尝试后才会被调用。 如果你正在尝试处理 Glide 的默认组件能处理的某些子类型 (例如一些特定的 Uri 授权或子类型),你可能需要使用 prepend() 来确保 Glide 的默认组件不会在你的定制组件之前加载。

要完全替换 Glide 的默认行为并确保它绝不运行,请使用 replace()replace() 将移除所有处理给定模型和数据类的 ModelLoaders,并添加你的 ModelLoader 来代替。 replace() 在使用库(例如 OkHttp 或 Volley)替换掉 Glide 的网络逻辑时尤其有用,这种时候你会希望确保仅 OkHttp 或 Volley 被调用。


参考链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容