1.用Modules()定制Glide
概述:Glide module是一个抽象方法,可以全局改变Glide行为的一个方式,
如果需要访问GlideBuider,需要创建Glide实例,定制Glide,需要实现一个GlideModule接口的公共类。
public class SimpleGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// todo
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
@Override
public void registerComponents(Context context, Glide glide) {
// todo
}
}
复制代码
可以看到GlideModule里面有两种方法,这个我们到后面再来讲。
定制完成类之后,下一步是要全局的去声明这个类,让Glide知道应该在哪里被加载和使用。Glide会去扫描AndroidManifest.xml为GlideModule的meta声明。
<application>
<meta-data
android:name="test.demo.SimpleGlideModule"
android:value="GlideModule" />
</application>
复制代码
这个android:name注意,属性明是,你这包名+类名的形式。如果你想删除该配置,直接在AndroidManifest.xml删除meta-data就OK。
我们去定制Module的Glide有个优点:你可以同时声明多个Glide module。Glide(没有特定顺序)得到所有的声明module。因为当前不能定义顺序,请确保定制不会引起冲突!
GlideBuilder
我们从上图可以看出GlideBuilder中的几个方法。
在这就说一下**.setDecodeFormat(DecodeFormat decodeFormat)方法。
可以设置Glide的图片质量
我们应该知道在android中有两种方法对图片进行解码:PREFER_ARGB_8888和PREFER_RGB_565**。前者每个像素使用了4个字节,后者每像素使用2个字节。可以知道前者图片质量更高,更能存储一个alpha通道。Glide默认使用RGB_565。如果使用者想改变解码规则。看代码
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// todo
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
复制代码
2.自定义内存缓存
其实分为:
- 内存缓存
- 磁盘缓存
内存缓存:是在设备的RAM中去维护图片的。没有IO操作,所以是很快的。但是RAM(内存)的大小非常有限。所以Glide内存使用了MemorySizeCalculator 类去决定内存缓存大小以及bitmap的缓存池。bitmap池维护了APP的堆中的图像分配。正确的bitmap池是非常必要的,因为它避免很多的图像重复回收,这样可以确保垃圾回收期的管理更加合理。
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
//1.获取内存缓存的大小与Bitmap位图池的大小
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
//2.app 需要 20% 大的缓存作为 Glide 的默认值
int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize);
int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);
builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));
builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
复制代码
我们现在所看到的,在builder设置的时候,不能直接设置大小,我们需要创建LruResourceCache和LruBitmapPool实例。如果想要调整大小,我们只需要传两个不同的大小值给构造函数。
磁盘缓存:
- 内部磁盘缓存
- APP自己能访问 **InternalCacheDiskCacheFactory **
- 应用外部也能访问 ExternalCacheDiskCacheFactory
- 外部磁盘缓存 DiskLruCacheFactory
- 外部添加
- 外部添加目录名称
具体我们看代码吧:
int cacheSize100MegaBytes = 104857600;
//设置内部缓存,只有当前APP有访问权限
builder.setDiskCache(
new InternalCacheDiskCacheFactory(context, cacheSize100MegaBytes)
);
//设置外部缓存,不止它自己能访问
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheSize100MegaBytes));
// or any other path
String downloadDirectoryPath = Environment.getDownloadCacheDirectory().getPath();
//如果你要让磁盘缓存到指定的目录,你要使用 DiskLruCacheFactory:
builder.setDiskCache(
new DiskLruCacheFactory(downloadDirectoryPath, cacheSize100MegaBytes)
);
//如果您想要指定一个缓存到自己设置的文件名
builder.setDiskCache(
new DiskLruCacheFactory(downloadDirectoryPath, "glidecache", cacheSize100MegaBytes)
);
复制代码
3.Module 实例:用自定义尺寸优化加载的图片
概述:当图像质量非常高时,可想而知对于设备的网速,内存和电池来说,这么做效率非常低。就算我们的手机屏幕分辨率非常高,也没有任何好处。所以Glide总是测量ImageView的尺寸,并减少图像的内存分配大小。这里任然需要减少下载和计算处理的开销。因此服务端给了一个细腻功能:它可以自动自定义图像的分辨率。
http://u-jia.deyi.com/2016/12/20/.jpg
http://u-jia.deyi.com/2016/12/20/.jpg?w=641&h=422
复制代码
其实这个w(宽)和h(高)就是,ImageView的宽高。我这测试的时候,发现当我们使用了.override(500, 300)属性,这个时候图片就会使用(500,300)当做图片的宽高,不再使用ImageView的宽高。可以自行测试。
自定义GlideModule
首先,必须声明一个新的Glidemodule,我们必须用glide.register() 方法注册新的 model 到 Glide。
public class CustomImageSizeGlideModule implements GlideModule {
@Override public void applyOptions(Context context, GlideBuilder builder) {
// nothing to do here
}
@Override public void registerComponents(Context context, Glide glide) {
glide.register(CustomImageSizeModel.class, InputStream.class, new CustomImageSizeModelFactory());
}
}
复制代码
从上可以看到,我们glide.register使用了,CustomImageSizeModel接口(替换常规的GlideUrL接口)。所以在这里你可以创建并传递一个 CustomImageSizeModel 的实例去实现给 Glide。 为了处理这个新的自定义 model。我们要去写一个 CustomImageSizeModelFactory 类,创建了我们的 model 处理的实例。
public interface CustomImageSizeModel {
String requestCustomSizeUrl(int width, int height);
}
复制代码
CustomImageSizeModel 只是一个接口,它将宽度和高度作为其参数,这是必须的,这样我们才能从服务端请求精确的像素图像。第二个未知的类是 CustomImageSizeModelFactory:
private class CustomImageSizeModelFactory implements ModelLoaderFactory<CustomImageSizeModel, InputStream> {
@Override
public ModelLoader<CustomImageSizeModel, InputStream> build(Context context, GenericLoaderFactory factories) {
return new CustomImageSizeUrlLoader( context );
}
@Override
public void teardown() {
}
}
复制代码
这个类仅仅实现了 Glide 的 ModelLoaderFactory 接口。它为我们的 CustomImageSizeUrlLoader 类创建了一个新的实例,一旦 Glide 请求被创建,它将负责加载图像。
public class CustomImageSizeUrlLoader extends BaseGlideUrlLoader<CustomImageSizeModel> {
public CustomImageSizeUrlLoader(Context context) {
super( context );
}
@Override
protected String getUrl(CustomImageSizeModel model, int width, int height) {
return model.requestCustomSizeUrl( width, height );
}
}
复制代码
这样,我们为自定义大小的请求的新的 Glide module 已经做完了。我们已经在 Glide module 这边实现了所有的东西的,但是我们还没有实际创建 CustomImageSizeModel 接口的实现。为了用 CustomImageSizeModel 传递请求给 Glide。我们需要一个雷,它建立了自定义图片大小的 URL:
public class CustomImageSizeModelFutureStudio implements CustomImageSizeModel {
String baseImageUrl;
public CustomImageSizeModelFutureStudio(String baseImageUrl) {
this.baseImageUrl = baseImageUrl;
}
@Override
public String requestCustomSizeUrl(int width, int height) {
// previous way: we directly accessed the images
// https://futurestud.io/images/logo.png
// new way, server could handle additional parameter and provide the image in a specific size
// in this case, the server would serve the image in 400x300 pixel size
// https://futurestud.io/images/logo.png?w=400&h=300
return baseImageUrl + "?w=" + width + "&h=" + height;
}
}
复制代码
在上面的 CustomImageSizeModelFutureStudio 类中,我们已经实现了建立图片 URL 的逻辑:附加了高度和宽度的参数。最后,我们可以创建这个类的实例并做一个 Glide 请求:
String baseImageUrl = "http://u-jia.deyi.com/2016/12/21/1e06021b5d6c86fcb69a8041eec000e5aa280f48_640x426.jpg";
CustomImageSizeModel customImageRequest = new CustomImageSizeModelFutureStudio( baseImageUrl );
Glide
.with( context )
.load( customImageRequest )
.into( imageView2 );
复制代码
我们可以看到,我们不需要传一个精确的尺寸,Glide会测量ImageView然后传给我们的请求。
Model Loader 和 .using() 的动态使用
如果我们声明了Glidemodule,Glide会把它用在每一个请求。如果不想这样 ,可以从AndroidManifest.xml 中删除你的 Glide module。因为Glide提供了 .using()方法为单个请求指定一个model。
String baseImageUrl = "http://u-jia.deyi.com/2016/12/21/1e06021b5d6c86fcb69a8041eec000e5aa280f48_640x426.jpg";
CustomImageSizeModel modelFutureStudio =
new CustomImageSizeModelFutureStudio(baseImageUrl);
Glide.with(getApplicationContext())
.using(new CustomImageSizeUrlLoader(getApplicationContext()))
.load(modelFutureStudio)
.into(iv_12);
复制代码
正如你看到的,我们正在创建一个 CustomImageSizeModelFutureStudio 对象来为我们的图像按照指定的大小加载。因为没有在 Glide module 中声明 CustomImageSizeModel 接口,我们必须指明这行代码 .using(new CustomImageSizeUrlLoader(context))。Glide 现在会只为这个请求用这个 model。对于其他的请求,即使它们有 CustomImageSizeModel 接口,也不会受影响。
原文地址:
mrfu.me/2016/02/28/…
DEMO地址:
github.com/z244370114/…