原文链接:http://bumptech.github.io/glide/
Github地址:https://github.com/bumptech/glide
上一篇:Android 图片加载(一)高效加载Bitmap 基础篇
一、Glide简介
Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道decode pipeline
,以及自动的资源池技术。
Glide支持拉取、解码和展示视频快照,图片和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection
的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。
(1)API设计
Glide使用简明的流式语法API,几行代码就能轻松实现图片加载。
Glide.with(this)
.load(url)
.into(imageView);
(2)性能
Glide充分考虑到Android图片加载性能的两个关键方面:
- 图片解码速度
- 解码图片带来的资源压力
为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。
Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:
- 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
- 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
- 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。
二、集成与使用
(1)Gradle集成
如果使用 Gradle,可从 Maven Central 或 JCenter 中添加对 Glide 的依赖。同样,你还需要添加 Android 支持库的依赖。
repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
}
dependencies {
compile 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}
注意:如果可能,请尽量在你的依赖中避免使用 @aar
。如果你必须这么做,请添加 transitive=true
以确保所有必要的类都被包含到你的 API 中:
dependencies {
implementation ("com.github.bumptech.glide:glide:4.8.0@aar") {
transitive = true
}
}
在 Gradle 中,@aar
意味着 “Artifact Only”,默认情况下将排除所有依赖。
如果你有使用到 proguard,那么请把以下代码添加到你的 proguard.cfg 文件中:
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
如果你的 target API 低于 Android API 27,请添加:
-dontwarn com.bumptech.glide.load.resource.bitmap.VideoDecoder
VideoDecoder 使用 API 27 的一些接口,这可能导致 proguard 发出警告,尽管这些 API 在旧版 Android 设备上根本不会被调用。
如果你使用 DexGuard 你可能还需要添加:
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
(2)基本用法
我们只需使用几行代码就能轻松实现图片加载:
Glide.with(this)
// .asGif() //加载GIF动图
.load(IMAGE_URL)
.into(imageView);
注:asGif只能加载gif动态图片,加载其他图片报错
我们也可以使用clear()
方法取消图片加载:
Glide.with(this).clear(imageView);
实际上,当 Glide.with()
中传入的 Activity 或 Fragment 实例销毁时,Glide会自动取消加载并回收资源。
(3)非 View 目标
除了将 Bitmap
和 Drawable
加载到 View
之外,你也可以开始异步加载到你的自定义 Target
中:
Glide.with(this)
.load("https://i9.hexun.com/2018-11-24/195299307.jpg")
.fitCenter()
.placeholder(R.drawable.leaf) //占位符
.into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
imageView.setImageDrawable(resource);
}
});
(4)后台线程
如果需要在后台线程加载图片,可以使用 submit(int, int)
:
new LoadTask().execute(IMAGE_URL);
private class LoadTask extends AsyncTask {
@Override
protected Drawable doInBackground(String... strings) {
FutureTarget futureTarget = Glide.with(GlideActivity.this)
.load(strings[0])
.fitCenter()
.placeholder(R.drawable.ic_launcher_foreground)
.submit(400,400);
try {
return futureTarget.get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Drawable drawable) {
super.onPostExecute(drawable);
imageView.setImageDrawable(drawable);
}
}
如果你不想让 Bitmap
或 Drawable
自身在后台线程中,你也可以使用和前台线程一样的方式来开始异步加载:
Glide.with(context)
.asBitmap()
.load(url)
.into(new Target() {
...
});
(5)其他常用配置
1、占位符
Glide允许用户指定三种不同类型的占位符,分别在三种不同场景使用:
- placeholder
当请求正在执行时被展示的。当请求成功完成时,占位符会被请求到的资源替换。如果被请求的资源是从内存中加载出来的,那么占位符可能根本不会被显示。如果请求失败并且没有设置error
,则占位符将被持续展示。类似地,如果请求的url/model为 null ,并且error
和fallback
都没有设置,那么占位符也会继续显示。
public static final String IMAGE_URL = "https://i9.hexun.com/2018-11-24/195299307.jpg";
Glide.with(this)
.load(IMAGE_URL)
.placeholder(R.drawable.leaf) //占位符
.into(imageView);
- error
在请求永久性失败时展示。同样也在请求的url/model为 null ,且没有设置fallback
时展示。
public static final String IMAGE_URL = "123";
Glide.with(this)
.load(IMAGE_URL)
.error(R.drawable.ic_launcher_background) //错误符
.into(imageView);
- fallback
在请求的url/model为 null 时展示。设计fallback
的主要目的是允许用户指示 null 是否为可接受的正常情况。例如,一个 null 的个人资料 url 可能暗示这个用户没有设置头像,因此应该使用默认头像。 默认情况下Glide将 null 作为错误处理,所以可以接受 null 的应用应当显式地设置一个fallback Drawable
。
public static final String IMAGE_URL = null;
Glide.with(this)
.load(IMAGE_URL)
.fallback(R.drawable.ic_launcher_background) //错误符
.into(imageView);
有几点需要注意:
- 占位符是在主线程从Android Resources加载的。
- Transformation仅被应用于被请求的资源,而不会对任何占位符使用。
- 对于有状态的 Drawable来说,多个View在同一时刻展示它们通常是不安全的,因为多个View可能会同时修改一个Drawable的状态信息。
2、请求选项
Glide中的大部分设置项都可以通过 RequestOptions
类和 apply()
方法来应用到程序中。
RequestOptions requestOptions = new RequestOptions()
.centerCrop() //设置scaleType
.skipMemoryCache(false) //内存缓存
.diskCacheStrategy(DiskCacheStrategy.ALL) //存储缓存策略
.error(R.drawable.ic_launcher_background); //错误符
Glide.with(this)
.load(IMAGE_URL)
.apply(requestOptions) //配置请求选项
.into(imageView);
apply()
方法可以被调用多次,因此 RequestOption
可以被组合使用。如果 RequestOptions
对象之间存在相互冲突的设置,那么只有最后一个被应用的 RequestOptions
会生效。
3、过渡选项
TransitionOptions用于决定你的加载完成时会发生什么。使用 TransitionOption 可以应用以下变换:
- View淡入
- 与占位符交叉淡入
- 或者什么都不发生
如果不使用变换,你的图像将会直接“跳入”其显示位置,替换掉之前的图像。为了避免这种突然的改变,你可以淡入view,或者让多个Drawable交叉淡入,而这些都需要使用TransitionOptions完成。
例如,要应用一个简单的交叉淡入变换:
Glide.with(this)
.load(IMAGE_URL)
.placeholder(R.drawable.ic_launcher_background)
.transition(DrawableTransitionOptions.withCrossFade(1000)) //配置过渡选项
.into(imageView);
不同于RequestOptions
,TransitionOptions
是特定资源类型独有的,你能使用的变换取决于你让Glide加载哪种类型的资源。
这样的结果是,假如你请求加载一个 Bitmap
,你需要使用 BitmapTransitionOptions ,而不是 DrawableTransitionOptions 。同样,当你请求加载 Bitmap
时,你只需要做简单的淡入,而不需要做复杂的交叉淡入。
4、缩略图请求
Glide 的 thumbnail()
API 允许你指定一个 RequestBuilder
与你的主请求并行启动。thumbnail()
会在主请求加载过程中展示,如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。thumbnail()
对本地和远程图片都适用,尤其是当低分辨率缩略图存在于 Glide 的磁盘缓存时,它们将很快被加载出来。
RequestBuilder thumbnailRequest = Glide.with(this).load(R.drawable.ic_launcher_background);
Glide.with(this)
.load(IMAGE_URL)
.thumbnail(thumbnailRequest)
.into(imageView);
只要你的 thumbnailUrl 指向的图片比你的主 url 的分辨率更低,它将会很好地工作。使用override
强制 Glide 在缩略图请求中加载一个低分辨率图像:
RequestBuilder thumbnailRequest = Glide.with(this)
.load(IMAGE_URL).override(100);
Glide.with(this)
.load(IMAGE_URL)
.thumbnail(thumbnailRequest)
.into(imageView);
thumbnail()
方法还有一个简化版本,它只需要一个 sizeMultiplier
参数。如果你只是想为你的加载相同的图片,但尺寸为 View
或 Target
的某个百分比的话特别有用:
Glide.with(this)
.load(IMAGE_URL)
.thumbnail(0.5f)
.into(imageView);
5、失败时开始新的请求
从 Glide 4.3.0 开始,可以使用 error
API 来指定一个RequestBuilder
,以在主请求失败时开始一次新的加载。
//请求空串失败后加载IMAGE_URL
RequestBuilder thumbnailRequest = Glide.with(this)
.load(IMAGE_URL).override(100);
Glide.with(this)
.load("")
.error(thumbnailRequest)
.into(imageView);
如果主请求成功完成,这个error RequestBuilder
将不会被启动。如果你同时指定了一个 thumbnail()
和一个 error()
RequestBuilder
,则这个后备的RequestBuilder
将在主请求失败时启动,即使缩略图请求成功也是如此。
下一篇:Android 图片加载(三)图片加载框架Glide 进阶篇