随着 Glide 从 V3 向 V4 的升级,API 的调用方式也发生了一些变化。这些变化主要集中在:选项、类型与目标、配置等方面。本文也会根据这几个方面结合官方文档对 API 变更做一个详细的阐述。在进行正式介绍 API 变更之前,我想非常有必要简述一下 Glide 的接入。这样,每位读者在阅读这篇文章的时候就不会感到陌生和生硬。
1 Android SDK 要求
版本 | 说明 |
---|---|
Min Sdk Version | 使用 Glide 需要 min SDK 版本 API 14 (Ice Cream Sandwich) 或更高。 |
Compile Sdk Version | Glide 必须使用 API 27 (Oreo MR1) 或更高版本的 SDK 来编译。 |
Support Library Version | Glide 使用的支持库版本为 27。 |
2 Glide 接入项目
如果您使用的 IDE 是 Android Studio,您可以从 Maven Central 或 JCenter 中添加对 Glide 的依赖。同样,你还需要添加 Android 支持库的依赖。
2.1 Project 接入
首先,你需要在 Project 所属的 build.gradle 文件中增加如下配置:
1 | repositories { |
2.2 Module 接入
其次,你需要在 Module 所属的 build.gradle 文件中增加如下依赖:
1 | dependencies { |
2.3 Manifest 权限配置
Glide 假定你要访问的数据都存储在你的应用中,不要求任何权限。也就是说,大部分应用从设备上(DCIM,图库,或SD卡的其他地方)或 Internet 上加载图片。因此,你可能需要包含一条或多条以下列出的权限,这取决于你的应用场景。
2.3.1 Internet 权限
如果你计划从 URL 或一个网络连接中加载数据,你需要添加 INTERNET 和 ACCESS_NETWORK_STATE 权限到你的 AndroidManifest.xml 中:
1 | <uses-permission android:name="android.permission.INTERNET" /> |
从技术上讲,ACCESS_NETWORK_STATE 对于 Glide 加载 URL 并不是必需的,但是它将帮助 Glide 处理片状网络(flaky network) 和飞行模式。
2.3.2 Local Storage 权限
要从本地文件夹或 DCIM 或图库中加载图片,你将需要添加 READ_EXTERNAL_STORAGE 权限:
1 | <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
而如果要使用 ExternalPreferredCacheDiskCacheFactory 来将 Glide 的缓存存储到公有 SD 卡上,你还需要添加 WRITE_EXTERNAL_STORAGE 权限:
1 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
2.4 加载图片
完成以上的配置后,你可以通过 Glide 加载一张图片来验证配置是否生效:
1 | Glide.with(fragment).load(url).into(imageView); |
3 Glide API 变更
3.1 选项
Glide V4 中的一个比较大的改动是 Glide 库处理选项 ( centerCrop(), placeholder() 等 ) 的方式。在 V3 版本中,选项由一系列复杂的异构建造者 ( multityped builders ) 单独处理。在新版本中,由一个单一类型的唯一一个建造者接管一系列选项对象。Glide 的 Generated API 进一步简化了这个操作:它会合并传入建造者的选项对象和任何已包含的集成库里的选项,以生成一个流畅的 API。
3.1.1 RequestBuilder 类
对于这类方法:listener()
、thumbnail()
、load()
、into()
,在 Glide v4 版本中,只存在一个 RequestBuilder 对应一个你正在试图加载的类型 (Bitmap, Drawable, GifDrawable 等)。 RequestBuilder 可以直接访问对这个加载过程有影响的选项,包括你想加载的数据模型(url, uri 等),可能存在的缩略图请求,以及任何的监听器。RequestBuilder 也是你使用 into() 或者 preload() 方法开始加载的地方:
1 | RequestBuilder<Drawable> builder = Glide.with(fragment).load(url); |
3.1.2 请求选项
对于这类方法:centerCrop()
、placeholder()
、error()
、priority()
、diskCacheStrategy()
,大部分选项被移动到了一个单独的称为 RequestOptions 的对象中:
1 | RequestOptions options = new RequestOptions() |
RequestOptions 允许你一次指定一系列的选项,然后对多个加载重用它们:
1 | RequestOptions options = new RequestOptions() |
3.1.3 变换
Glide V4 里的 Transformations 现在会替换之前设置的任何变换。在 Glide V4 中,如果你想应用超过一个的 Transformation,你需要使用 transforms() 方法:
1 | Glide.with(fragment) |
或使用 Generated API,使用 Generated API 之前你需要新建一个类继承 AppGlideModule,并在该类上添加注解 @GlideModule,注意这里的 glideName 参数,这个参数的值默认是 GlideApp,这个值就是你使用 Generated API 进行调用的入口。如果采用默认值,那么你的调用将以 GlideApp.with(fragment)
开始,如果这个值是自定义的,比如 @GlideModule(glideName = "MyGlideApp")
,那么,你的调用将以 MyGlideApp.with(fragment)
开始。
1 | package com.sunzn.glide; |
下面的调用采用默认值 GlideApp 进行调用:
1 | GlideApp.with(fragment) |
提示:如果你正确增的加了 AppGlideModule 的继承类,但是在 Android Studio 中却找不到调用入口,这时你可以尝试 Rebuild Progect 或者直接运行代码。
3.1.4 解码格式
在 Glide V3, 默认的 DecodeFormat 是 DecodeFormat.PREFER_RGB_565,它将使用 [Bitmap.Config.RGB_565],除非图片包含或可能包含透明像素。对于给定的图片尺寸,RGB_565 只使用 [Bitmap.Config.ARGB_8888] 一半的内存,但对于特定的图片有明显的画质问题,包括条纹(banding)和着色(tinting)。为了避免 RGB_565 的画质问题,Glide 现在默认使用 ARGB_8888。结果是,图片质量变高了,但内存使用也增加了。
要将 Glide v4 默认的 DecodeFormat 改回 DecodeFormat.PREFER_RGB_565,请在 AppGlideModule 中应用一个 RequestOption:
1 |
|
关于使用 AppGlideModules 的更多信息,请查阅 配置 页面。请注意,为了让 Glide 发现你的 AppGlideModule 实现,你必须确保添加了对 Glide 的注解解析器的依赖。关于如何设置这个库的更多信息,请查看 下载和设置。
3.1.5 过渡选项
对于这类方法:crossFade()
、animate()
控制从占位符到图片和/或缩略图到全图的交叉淡入和其他类型变换的选项,被移动到了 TransitionOptions 中。
要应用过渡(之前的动画),请使用下列选项中符合你请求的资源类型的一个:
如果你想移除任何默认的过渡,可以使用 TransitionOptions.dontTransition() 。
过渡动画通过 RequestBuilder 应用到请求上:
1 | import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade; |
3.1.5.1 交叉淡入 (Cross fade)
不同于 Glide V3,Glide V4 将不会默认应用交叉淡入或任何其他的过渡效果。每个请求必须手动应用过渡。
要为一个特定的加载应用一个交叉淡入变换效果,你可以使用以下方式中的任何一种:
1 | import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade; |
1 | Glide.with(fragment) |
1 | Glide.with(fragment) |
3.1.5.2 动画进入 (Animate)
动画进入的使用与交叉淡入类似,也被移动到了 TransitionOptions 中。而与 Animate 相关的方法正是在 TransitionOptions 类中:
1 |
|
由于 TransitionOptions 是抽象类,所以在使用的时候只能使用它的实现类 GenericTransitionOptions、DrawableTransitionOptions 或 BitmapTransitionOptions 的实例来完成:
1 | Glide.with(fragment) |
3.1.6 Generated API
为了让使用 Glide V4 更简单轻松,Glide 现在也提供了一套可以为应用定制化生成的 API。应用可以通过包含一个标记了 AppGlideModule 的实现来访问生成的 API。如果你不了解这是怎么工作的,可以查看 Generated API。
Generated API添加了一个 GlideApp 类,该类提供了对 RequestBuilder 和 RequestOptions 子类的访问。RequestOptions 的子类包含了所有 RequestOptions 中的方法,以及 GlideExtensions 中定义的方法。RequestBuilder 的子类则提供了生成的 RequestOptions 中所有方法的访问,而不需要你再手动调用 apply 。举个例子:
在没有使用 Generated API 时,请求大概长这样:
1 | Glide.with(fragment) |
使用 Generated API,RequestOptions 的调用可以被内联:
1 | GlideApp.with(fragment) |
你仍然可以使用生成的 RequestOptions 子类来应用相同的选项到多次加载中;但生成的 RequestBuilder 子类可能在多数情况下更为方便。
3.2 类型与目标
3.2.1 选择资源类型
Glide 允许你指定你想加载的资源类型。如果你指定了一个超类型,Glide 会尝试加载任何可用的子类型。比如,如果你请求的是 Drawable ,Glide 可能会加载一个 BitmapDrawable 或一个 GifDrawable 。而如果你请求的是一个 GifDrawable ,要么会加载出一个 GifDrawable,要么报错–只要图片不是 GIF 的话(即使它凑巧是一个完全有效的图片也是如此)。
默认请求的类型是 Drawable:
1 | Glide.with(fragment).load(url) |
如果要明确指定请求 Bitmap:
1 | Glide.with(fragment).asBitmap() |
如果要创建一个文件路径(本地图片的最佳选项):
1 | Glide.with(fragment).asFile() |
如果要下载一个远程文件到缓存然后创建文件路径:
1 | Glide.with(fragment).downloadOnly() |
3.2.2 Drawables
Glide v3 版本中的 GlideDrawable 类已经被移除,支持标准的 Android Drawable。 GlideBitmapDrawable 也已经被删除,由 BitmapDrawable 代替之。
如果你想知道某个 Drawable 是否是动画(animated),可以检查它是否为 Animatable 的实例。
1 | boolean isAnimated = drawable instanceof Animatable; |
3.2.3 Targets
onResourceReady 方法的签名做了一些修改。例如,对于 Drawables:
1 | onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) |
现在改为:
1 | onResourceReady(Drawable drawable, Transition<? super Drawable> transition); |
类似地,onLoadFailed 的签名也有一些变动:
1 | onLoadFailed(Exception e, Drawable errorDrawable) |
改为:
1 | onLoadFailed(Drawable errorDrawable) |
如果你想要获得更多导致加载失败的错误信息,你可以使用 RequestListener。
3.2.3.1 ViewTarget 的使用
最后,普及一下 ViewTarget 的使用方式,否则,部分开发者可能对 onResourceReady 和 onLoadFailed 签名的改变没有直观的概念。ViewTarget 的使用大概如下:
1、编写自定义的 ViewTarget,覆盖需要实现的方法。
1 | package com.sunzn.glide; |
2、将自定义的 ViewTarget 传入 into() 方法。
1 | ImageView imageView = findViewById(R.id.iv); |