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()); } }