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之间的顺序,我们可以根据实际需求选用。

  • prepend()

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

  • append()

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

  • replace()

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


参考链接

  • Android图片加载框架最全解析(六),探究Glide的自定义模块功能
  • http://bumptech.github.io/glide/

你可能感兴趣的:(Android 图片加载(四)Glide自定义模块)