从接触应用层开发开始,图片相关的功能一直都是Android开发人员比较关注的问题,从最开始的ImageLoader,到Square公司开发的Picasso图片加载框架,再到如今的主流图片加载框架Glide,其实我们都知道这几个图片框架的核心都离不开缓存,内存缓存和磁盘缓存,两者结合极大程度的提高了图片的加载效率。但是我们从框架中学到远不止这些,接下来我会分几篇来分析下Glide框架到底为何能成为主流的图片加载框架呢,首先看看它的一些常用的使用方式。
基本使用
本次我们使用glide4.9.0版本来讲述功能和代码,首先需要在gradle中配置:
repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
}
dependencies {
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
}
不要忘记了添加权限~
混淆文件:
-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
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
常规加载图片
Glide.with(this)
.load(imgUrl)
.into(imageView);
绝大多数加载图片的功能都能用上面一行代码解决,除了部分需要特定场景的需求,则需要用到Glide的其他功能,我们来看下加载的效果图
加载占位图
Glide官方提供的占位图有三种,分别是Placeholder,Error,FallBack。
- Placeholder主要用于当前我们加载的图片还未成功显示的时候作为当前图片的临时显示,如果请求图片一直没有成功,并且没有设置Error和FallBack占位图,那么Placeholder占位图则会一直显示。
- Error则是用于当我们的图片加载失败了会显示,当没有设置FallBack的时候,那么Error占位图则会一直显示。
- FallBack则是表示如果所加载的图片文件或者URL为空,那么这个时候加载的就是FallBack占位图,相当于是view加载没有获取到图片的url时候加载的默认图。
Placeholder占位图的使用
Glide.with(this)
.load(url)
.placeholder(new ColorDrawable(Color.GREEN))
.into(view);
这里我们给Placeholder设置本地drawable资源和设置背景色都行,为了省时间我设置的背景色,我们来看看添加背景色占位图后的效果,这里为了能够清晰的看出效果,选择了比较明亮的原谅色,正常的开发中使用较多的还是灰白色的占位图。
Error占位图的使用
Glide.with(this)
.load(url)
.error(new ColorDrawable(Color.RED))
.into(view);
这里给Error设置的红色,功能和Placeholder一样,我关闭了网络请求权限,显示的则是一直请求出错的占位图。
FallBack占位图的使用
Glide.with(this)
.load(url)
.fallback(new ColorDrawable(Color.BLUE))
.into(view);
RequestOptions
通常情况下,一般的链式调用能满足我们的需求,但是glide也提供了这样的功能,当我们加载多个img时,必定需要多次去使用glide和设置加载的选项,那么如果这些选项存在公共的设置,应该可以提取出来,那么这是options的作用了,单独提取出来也使代码更简洁,我们来看看使用方式:
RequestOptions requestOptions = new RequestOptions()
.error(new ColorDrawable(Color.RED))
.centerCrop();
Glide.with(this)
.load(url)
.apply(requestOptions)
.into(view);
TransitionOptions
TransitionOptions一般用于当图片加载完成后,如果设置了占位图,那么是获取到的图片替换掉占位图的一个过度动画,例如淡入淡出,羡慕就尝试使用淡入的效果设置加载完成后TransitionOptions的设置;看运行结果和Placeholder占位图的绿色背景比较,明显在设置图片的时候有了 一个缓慢的过渡,这样避免了图片闪过的场景。
Glide.with(this)
.load(url)
.placeholder(new ColorDrawable(Color.GREEN))
.transition(withCrossFade())
.into(view);
RequestBuilder
RequestBuilder相对比较灵活,它携带了一个图片加载的几个重要元素,包括请求的rul和常规的设置(占位图,Options,缩略图等),针对不同的需求,我们同样也能单独先创建RequestBuilder,然后再去load(url)和into(view),看看下面的例子:
RequestBuilder requestBuilder = Glide.with(this).asDrawable();
requestBuilder.load(url).into(view);
Thumbnail
Thumbnail表示缩略图,当我们请求图片还未能加载的时候,可以选择优先展示另一个缩略图的图片url,直到原图片展示成功,这样对于用户来说是友好的。
Glide.with(this)
.load(url)
.thumbnail(Glide.with(this)
.load(thumbnailUrl))
.into(imageView);
如果加载的图片只有一个url,而没有缩略图的url,那么你可以像下面这么做,在thumbnail里面设置图片的宽高,则执行加载指定宽高的缩略图,最终效果如下,可以清晰的看到在显示原图之前有一个缩略图的过渡,这样看起来效果是不是比最初的直接load好多了呢?
Glide.with(this)
.load(url)
.placeholder(new ColorDrawable(Color.GREEN))
.transition(withCrossFade())
.thumbnail(Glide.with(this).load(url).override(60))
.into(imageView);
SizeMultiplier
如果你想加载一张图片的缩略图,那么sizeMultiplier表示为这张图缩小多少比例,如下设置为缩小四分之一
Glide.with(this)
.load(url)
.thumbnail(/*sizeMultiplier*/ 0.25f)
.into(imageView);
请求失败后再次请求
这种做法类似于thumbnail,当mainurl请求失败后,则会去请求twourl,当我们同时设置了thumbnail请求,那么它只会在mainurl请求失败后去再次请求;
Glide.with(this)
.load(mainurl)
.error(Glide.with(this)
.load(twourl))
.into(imageView);
Transformations
通常Transformations 用来对获取的图片资源进行裁剪、缩放、GIF动画转换等操作,一般情况下Glide提供了CenterCrop、FitCenter、CircleCrop的内置转换,单独使用或者结合RequestOptions使用,如下使用:
Glide.with(this)
.load(mainurl)
.centerCrop()
.into(imageView);
如果使用多个转换,MultiTransformation可以省略,CustomTransformation为自定义的Transformation,MultiTransformation构造函数的传入参数的顺序,决定了这些转换的实现顺序,如果效果重合,那么后面的参数效果会覆盖前面的效果,那么需要如下使用方式:
Glide.with(fragment)
.load(url)
.transform(new MultiTransformation(new centerCrop(), new CustomTransformation())
.into(imageView);
如果对图片有特定的转换需求,那么需要定制化transformation,Glide为我们提供了许多Transformation,假如我们需要对bitmap特定转化,那么可以使用BitmapTransformation,使用方法如下:
public class CustomTrans extends BitmapTransformation {
private static final String ID = "com.glide.demo.CustomTrans";
private static String ID_BYTES = null;
static {
try {
ID_BYTES = String.valueOf(ID.getBytes(STRING_CHARSET_NAME));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Override
public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {
return toTransform;
}
//操作图片,得到新的bitmap
return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, /*filter=*/ true);
}
/**
* 下面三个方法必须重写,将当前类的hashcode作为当前转换的bitmap的key
* 便于存储到磁盘和内存,那么下次获取则通过当前key获取缓存
* @param
*/
@Override
public boolean equals(Object o) {
return o instanceof CustomTrans;
}
@Override
public int hashCode() {
return ID.hashCode();
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
messageDigest.update(Byte.parseByte(ID_BYTES));
}
}
缓存设置
Glide.with(this)
.load(mainurl)
//跳过内存缓存
.skipMemoryCache(true)
//缓存所有版本的图像
.diskCacheStrategy(DiskCacheStrategy.ALL)
//跳过磁盘缓存
.diskCacheStrategy(DiskCacheStrategy.NONE)
//只缓存原来分辨率的图片
.diskCacheStrategy(DiskCacheStrategy.DATA)
//只缓存最终的图片
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(imageView);
总结
关于一些常规的Glide使用方法暂时总结到这里,后面会陆续再补充的更全面,本篇文章也会陆续更新,下一章我们一起看下Glide源码,一共会分几个层面来解析,如有什么疑问也能提出,随时修正和改进。最后放出官方文档和源码地址:
Github地址:https://github.com/bumptech/glide
官方文档:http://bumptech.github.io/glide/
官方文档中文版:https://muyangmin.github.io/glide-docs-cn/
Glide源码之如何绑Activity的生命周期的