Android图片缓存之Glide进阶
前言:
前面学习了Glide的简单使用(Android图片缓存之初识Glide),今天来学习一下Glide稍微复杂一点的使用。
图片缓存相关博客地址:
GlideModule使用:
GlideModule 是一个抽象方法,全局改变 Glide 行为的一个方式,通过全局GlideModule 配置Glide,用GlideBuilder
设置选项,用Glide注册ModelLoader等。
1.)自定义一个GlideModule
public class MyGlideModule implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { // Apply options to the builder here. } @Override public void registerComponents(Context context, Glide glide) { // register ModelLoaders here. } }
2.)AndroidManifest.xml注册
<manifest ...> <!-- ... permissions --> <application ...> <meta-data android:name="com.mypackage.MyGlideModule" android:value="GlideModule" /> <!-- ... activities and other components --> </application> </manifest>
3.)添加混淆处理
-keepnames class com.mypackage.MyGlideModule
# or more generally:
#-keep public class * implements com.bumptech.glide.module.GlideModule
4.)多个GlideModule冲突问题
GlideModule不能指定调用顺序,所以应该避免不同的GlideModule之间有冲突的选项设置,可以考虑将所有的设置都放到一个GlideModule里面,或者排除掉某个manifest文件的某个Module,代码如下:
<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”remove” />
GlideBuilder
设置选项:
1.)设置Glide内存缓存大小
int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小 int memoryCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一 //设置内存缓存大小 builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
获取默认的内存使用计算函数
MemorySizeCalculator calculator = new MemorySizeCalculator(context); int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
2.)设置Glide磁盘缓存大小
File cacheDir = context.getExternalCacheDir();//指定的是数据的缓存地址 int diskCacheSize = 1024 * 1024 * 30;//最多可以缓存多少字节的数据 //设置磁盘缓存大小 builder.setDiskCache(new DiskLruCacheFactory(cacheDir.getPath(), "glide", diskCacheSize));
也可以通过如下两种方式
//存放在data/data/xxxx/cache/ builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide", diskCacheSize)); //存放在外置文件浏览器 builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "glide", diskCacheSize));
3.)设置图片解码格式
//设置图片解码格式 builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
默认格式RGB_565使用内存是ARGB_8888的一半,但是图片质量就没那么高了,而且不支持透明度
4.)设置缓存内存大小
//设置BitmapPool缓存内存大小 builder.setBitmapPool(new LruBitmapPool(memoryCacheSize));
5.)设置一个用来检索cache中没有的Resource的ExecutorService
为了使缩略图请求正确工作,实现类必须把请求根据Priority优先级排好序。
builder.setDiskCacheService(ExecutorService service);
builder.setResizeService(ExecutorService service);
使用ModelLoader自定义数据源:
例如我们使用了七牛云存储,要根据不同的要求请求不同尺寸不同质量的图片,这时我们就可以使用自定义数据源
1.)定义处理URL接口
public interface IDataModel { String buildDataModelUrl(int width, int height); }
2.)实现处理URL接口
JpgDataModel
public class JpgDataModel implements IDataModel { private String dataModelUrl; public JpgDataModel(String dataModelUrl) { this.dataModelUrl = dataModelUrl; } @Override public String buildDataModelUrl(int width, int height) { //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/jpg return String.format("%s?imageView2/1/w/%d/h/%d/format/jpg", dataModelUrl, width, height); } }
WebpDataModel
public class WebpDataModel implements IDataModel { private String dataModelUrl; public WebpDataModel(String dataModelUrl) { this.dataModelUrl = dataModelUrl; } @Override public String buildDataModelUrl(int width, int height) { //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/webp return String.format("%s?imageView2/1/w/%d/h/%d/format/webp", dataModelUrl, width, height); } }
3.)实现ModelLoader
public class MyDataLoader extends BaseGlideUrlLoader<IDataModel> { public MyDataLoader(Context context) { super(context); } public MyDataLoader(ModelLoader<GlideUrl, InputStream> urlLoader) { super(urlLoader, null); } @Override protected String getUrl(IDataModel model, int width, int height) { return model.buildDataModelUrl(width, height); } /** */ public static class Factory implements ModelLoaderFactory<IDataModel, InputStream> { @Override public ModelLoader<IDataModel, InputStream> build(Context context, GenericLoaderFactory factories) { return new MyDataLoader(factories.buildModelLoader(GlideUrl.class, InputStream.class)); } @Override public void teardown() { } } }
4.)根据不同的要求采用不同的策略加载图片
//加载jpg图片 Glide.with(this).using(new MyDataLoader(this)).load(new JpgDataModel(imageUrl)).into(imageView); //加载webp图片 Glide.with(this).using(new MyDataLoader(this)).load(new WebpDataModel(imageUrl)).into(imageView);
5.)如何跳过.using()
public class MyGlideModule implements GlideModule { ... @Override public void registerComponents(Context context, Glide glide) { glide.register(IDataModel.class, InputStream.class, new MyUrlLoader.Factory()); } }
上面的实现跳过using()
//加载jpg图片 Glide.with(this).load(new JpgDataModel(imageUrl)).into(imageView); //加载webp图片 Glide.with(this).load(new WebpDataModel(imageUrl)).into(imageView);
使用signature()实现自定义cacheKey:
Glide 以 url、viewwidth、viewheight、屏幕的分辨率等做为联合key,官方api中没有提供删除图片缓存的函数,官方提供了signature()方法,将一个附加的数据加入到缓存key当中,多媒体存储数据,可用MediaStoreSignature类作为标识符,会将文件的修改时间、mimeType等信息作为cacheKey的一部分,通过改变key来实现图片失效相当于软删除。
1.)使用StringSignature
Glide.with(this).load(yourFileDataModel).signature(new StringSignature("1.0.0")).into(imageView);
2.)使用MediaStoreSignature
Glide.with(this) .load(mediaStoreUri).signature(new MediaStoreSignature(mimeType, dateModified, orientation)).into(view);
3.)使用自定义Signature
public class IntegerVersionSignature implements Key { private int currentVersion; public IntegerVersionSignature(int currentVersion) { this.currentVersion = currentVersion; } @Override public boolean equals(Object o) { if (o instanceof IntegerVersionSignature) { IntegerVersionSignature other = (IntegerVersionSignature) o; return currentVersion = other.currentVersion; } return false; } @Override public int hashCode() { return currentVersion; } @Override public void updateDiskCacheKey(MessageDigest md) { messageDigest.update(ByteBuffer.allocate(Integer.SIZE) .putInt(signature).array()); } }
小结:
今天学了Glide的一些自定义扩展知识,接下来学习一下Glide与OKHttp的结合,已经简单探析一下内部使用。
干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!