在项目中配置Glide4
要想在项目中使用Glide4,需要先将这个库引入到我们的项目中,依赖方式如下:
implementation 'com.github.bumptech.glide:glide:4.4.0'
另外,Glide中需要使用网络权限,因此需要在清单文件中声明网络权限才行。
Glide4的使用
配置完成后,我们就可以使用Glide中的任意功能了。
加载图片
Glide4加载图片的方法与Glide3是一致的,只要通过以下方式就可以轻松的将图片加载到ImageView控件上了。
Glide.with(GlideTestActivity.this).load(imgUrl).into(iv);
RequestOptions
在Glide4中引入了一个RequestOptions对象,Glide4将许多Glide3中的Api操作都转移到这个对象中来,如占位图、缓存等操作,这样做的好处是可以使我们摆脱冗长的Glide加载语句。接下来我们来解析一下这个对象的用法。
1、占位图
Glide在加载图片时需要把图片从网络上下载下来,这个过程需要一定的时间,所以控件要等待一段时间才能把图片显示出来,在这个期间,我们可以使用一张占位图暂时替代直到目标图片加载完成再将其替换;另一种情况是图片加载失败而现实的异常占位图。而Glide就提供了占位图的功能。占位图的用法如下所示:
RequestOptions options = new RequestOptions()
.placeholder(R.mipmap.ic_launcher)//加载时的占位图
.error(R.drawable.img_error);//加载异常之后显示的占位图
Glide.with(GlideTestActivity.this).load(imgUrl).apply(options).into(iv);
2、指定图片的大小
实际上,使用Glide在大多数情况下我们是不需要指定图片大小的,因为Glide会根据ImageView的大小自动调节图片的大小以确保图片不会占用太多内存而引发OOM。但是如果你有这样的需求要指定图片的大小,Glide也提供了这个功能的支持。具体用法如下:
final RequestOptions options = new RequestOptions().override(180, 180);
Glide.with(GlideTestActivity.this).load(imgUrl).apply(options).into(iv);
当然,如果你不想压缩图片,你可以在override方法中传入Target.SIZE_ORIGINAL参数,但是要注意OOM的风险。
3、缓存机制
Glide的缓存分为两个模块:内存缓存和磁盘缓存。内存缓存主要作用是防止应用重复将图片读取到内存中,而硬盘缓存的主要作用是防止应用重复从网络或者其他地方重复下载和读取数据。
首先来看内存缓存,默认情况下Glide是自动开启内存缓存的。也就是说。当我们使用Glide加载一张图片后,这张图片就会被缓存到内存中,只要它没有从内存中被清除,那么你下次使用Glide加载这张图片时就会直接从内存中读取。如果你由于某种原因不需要开启内存缓存功能,你可以通过以下方式禁用内存缓存:
RequestOptions options = new RequestOptions().skipMemoryCache(true);
Glide的硬盘缓存可以通过RequestOptions的diskCacheStrategy()方法进行配置,这个方法可以接收下列五个参数:
- DiskCacheStrategy.NONE:表示不缓存任何内容。
- DiskCacheStrategy.DATA:表示只缓存原始图片。
- DiskCacheStrategy.RESOURCE:表示只缓存转换后的图片。
- DiskCacheStrategy.ALL:表示既缓存原始图片也缓存转换后的图片。
- DiskCacheStrategy.AUTOMATIC:表示让Glide根据图片资源智能的选择使用哪一种缓存策略(默认选项)。
当我们使用Glide去加载一张图片的时候,Glide默认并不会将原始图片展示出来,而是会对图片进行压缩转换。
4、图片变换
图片变换是指Glide加载完图片到最终展示给用户之前,又进行了一些变化处理,从而实现一些更加丰富的图片效果,如圆角化、圆形化、模糊等。添加图片变换的用法非常简单,我们只需要在RequestOptions中串接transforms()方法,并将要执行的图片变换依次作为参数传入即可。Glide内置了几种图片变换,如CenterCrop、FilterCenter、CircleCrop等,但这些操作可以不使用transforms()方法,因为Glide为我们直接提供了API,如圆形化我们可以通过以下代码进行实现:
RequestOptions options = new RequestOptions().circleCrop();
Glide.with(GlideTestActivity.this).load(imgUrl).apply(options).into(iv);
除了内置的图片变换外,我们还可以自定义自己的图片变化操作。关于图片变化有一个非常优秀的开源库,glide-transformations。它实现了很多通用的图形变化效果,如裁剪、颜色变换、模糊等,它的项目地址是:https://github.com/wasabeef/glide-transformations 。在使用前,我们需要在项目中引入依赖:
implementation 'jp.wasabeef:glide-transformations:3.0.1'
我们可以对图片进行单个变换处理,也可以将多种图片变换叠加在一起使用,示例代码如下:
RequestOptions options = new RequestOptions()
.transforms(new ColorFilterTransformation(Color.argb(80, 255, 0, 0)), new BlurTransformation());
Glide.with(this).load("http://pic41.nipic.com/20140429/12728082_192158998000_2.jpg").apply(options).into(iv);
当然,这只是glide-transformations库的一小部分功能,更多的变换效果可到Github项目主页学习。
指定格式加载
我们都知道Glide是可以加载GIF图的,Glide加载GIF图并不用编写什么额外的代码,Glide内部会自动判断图片格式。如果这时候要这么一种需求,无论我加载的图片是否为GIF图,我都希望加载一张静态图呢?在Glide3中有一个asBitmap()的方法,在Glide4中同样有这个方法,不同的地方在于Glide3中这个方法是在load()方法之后调用的,而Glide4中这个方法要在load()之前调用,否则会报错哦,调用此方法后,Glide将显示GIF图的第一帧。同样的,我们能强制加载静态图片就也能强制加载动态图片,加载动态图的方法为asGif()。在Glide4中还新增了asFile()和asDrawable()的方法。
回调与监听
1、into()方法
我们都知道Glide的into()方法可以传入一个ImageView参数,那么into()方法还可以传入其他类型的参数吗?答案是可以的,这就需要用到自定义Target功能了。下面我们来演示一个SimpleTarget的示例代码:
SimpleTarget<Drawable> target = new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
iv.setImageDrawable(resource);
}
};
Glide.with(this).load(imgUrl).into(target);
在示例中,我们创建了一个SimpleTarget对象。指定泛型为Drawable,然后重写onResourceReady方法,在这个方法中我们就能够获取到Glide加载出来的Drawable对象了,有了这个对象之后我们就可以使用它进行任意逻辑操作,而不仅限于将其展示到控件上了。
2、preload()方法
如果我们希望对一张图片进行预加载从而达到更好的用户体验,那么我们就可以使用preload()方法实现。preload()方法有两个重载方法,一个不带参数,表示加载图片原始尺寸;另一个通过参数指定加载图片的宽高。preload()方法的使用很简单,只要用它来替代into()方法就可以了。调用预加载后,下次我们再去加载这张图片就会很快了。
3、submit()方法
我们都知道使用Glide加载图片会将图片进行缓存,可是缓存到哪里?如何访问这些缓存图片?我们都不知道。在此,我们可以使用submit()方法。submit()方法与Glide3中的downloadOnly()方法是一致的,它的用法也是直接替换into方法,它只会下载图片而不会对图片进行加载。submit()方法也包含两个重载方法,一个不带参数下载原始图片的方法;一个带参数下载指定宽高图片的方法。它的用法如下所示:
new Thread(new Runnable() {
@Override
public void run() {
FutureTarget<File> submit = Glide
.with(GlideTestActivity.this)
.asFile()
.load("http://guolin.tech/test.gif")
.submit();
try {
final File file = submit.get();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(GlideTestActivity.this,file.getPath(),Toast.LENGTH_SHORT).show();
}
});
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
submit()方法必须在子线程中调用,在上面的代码中我们使用Application类型的Context对象是因为用Activity作为Context对象可能会出现Activity销毁了而子线程还没执行完这种可能。此方法会返回一个FutureTarget对象,我们指定返回一个File泛型的FutureTarget对象,可以通过此对象的get()方法获取下载的图片文件,get()方法是一个阻塞方法,如果图片还没有下载好线程会在此阻塞,等到下载完成后返回File对象。这样,我们就可以拿到图片完整的缓存路径了。
4、listener()方法
listener()方法用于监听Glide加载图片的状态。比如我们之前的preload()方法,我要怎么才能知道预加载有没有完成呢?如果图片加载失败了,我要怎么知道加载失败的原因呢?在这里我们就可以使用listener()进行监听了。listener()方法可以分别与preload()方法和into()方法进行结合使用,其使用方式如下:
Glide.with(this).load(url)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model
, Target<Drawable> target, boolean isFirstResource) {
e.printStackTrace();
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target
, DataSource dataSource, boolean isFirstResource) {
Log.e("tag", "加载完成");
return false;
}
}).into(iv);
上述代码中两个方法都有一个boolean类型的返回值,返回值的含义代表着这个事件有没有被处理,返回false表示未处理,事件会继续往下传递,返回true表示已处理,事件不再传递。如onResourceReady()方法若返回true,则into()中的Target参数的onResourceReady()将不再回调。
参考资料: