Glide之GlideModule
2016-03-31 15:13
323 查看
GlideModule接口:为了延迟配置Glide(包括用
GlideBuilder设置选项,为Glide注册
ModelLoader)
所有的GlideModule实现类必须是public的,并且只拥有一个空的构造器,以便在Glide延迟初始化时,可以通过反射将它们实例化。注册
ModelLoader时可调用Glide的
register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory)方法进行注册,如:
public class MyGlideModule implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { buidler.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); } @Override public void registerComponents(Context context, Glide glide) { glide.register(Model.class, Data.class, new MyModelLoaderFactory()); } }
配置proguard.cfg以允许你的GlideModule可以通过反射实例化:
-keepnames class * com.mypackage.MyGlideModule
或者把所有的Module都一次性配置好:
-keep public class * implements com.bumptech.glide.module.GlideModule
然后将你的GlideModule加入
AndroidManifest.xml文件中的meta-data标签,key是实现类的全限定名,value是GlideModule,如:
<meta-data android:name="com.mypackage.MyGlideModule" android:value="GlideModule" />
如果GlideModule没有在
AndroidManifest.xml中被引用,那它就不会被加载或使用。所以可以把不用的GlideModule从
AndroidManifest.xml中删掉就可以了,不一定非要删除对定的java文件。
GlideModule不能指定调用顺序,所以应该避免不同的GlideModule之间有冲突的选项设置,可以考虑将所有的设置都放到一个GlideModule里面,或者排除掉某个manifest文件的某个Module,像这样:
<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”remove” />
======================================
好了,现在来看接口的第一个方法
void applyOptions(Context context, GlideBuilder builder)。用来在Glide单例创建之前应用所有的选项配置,该方法每次实现只会被调用一次。通过GlideBuilder(Glide的创造者)我们可以对Glide进行各种配置:
setBitmapPool(BitmapPool bitmapPool).
Bitmap池用来允许不同尺寸的Bitmap被重用,这可以显著地减少因为图片解码像素数组分配内存而引发的垃圾回收。默认情况下Glide使用
LruBitmapPool作为Bitmap池,
LruBitmapPool采用LRU算法保存最近使用的尺寸的Bitmap。我们可以通过它的构造器设置最大缓存内存大小:
builder.setBitmapPool(new LruBitmapPool(sizeInBytes));
setMemoryCache(MemoryCache memoryCache).
MemoryCache用来把resources 缓存在内存里,以便能马上能拿出来显示。默认情况下Glide使用
LruResourceCache,我们可以通过它的构造器设置最大缓存内存大小:
builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));
MemoryCache和BitmapPool的默认大小由
MemorySizeCalculator类决定,MemorySizeCalculator会根据给定屏幕大小可用内存算出合适的缓存大小,这也是推荐的缓存大小,我们可以根据这个推荐大小做出调整:
MemorySizeCalculator calculator = new MemorySizeCalculator(context); int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize); int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize); builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize)); builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
setDiskCache(final DiskCache diskCache).
设置一个用来存储
Resource数据和缩略图的DiskCache实现。注意:在主线程中创建磁盘缓存目录会导致严格模式下的违规,用setDiskCache(DiskCache.Factory)替代,Glide4.0打算移除该方法。
setDiskCache(DiskCache.Factory diskCacheFactory).
设置一个用来创建DiskCache的工厂。默认情况下Glide使用
InternalCacheDiskCacheFactory内部工厂类创建DiskCache,缓存目录为程序内部缓存目录image_manager_disk_cache(不能被其它应用访问)且缓存最大为250MB。当然,可以通过
InternalCacheDiskCacheFactory构造器更改缓存目录和最大缓存大小,如:
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));
还可以指定缓存到外部磁盘SD卡上:
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));
缓存架构的接口包括:
com.bumptech.glide.load.engine.cache.DiskCache
com.bumptech.glide.load.engine.cache.DiskCache.Factory
com.bumptech.glide.load.engine.cache.DiskCache.Writer
com.bumptech.glide.load.engine.cache.DiskLruCacheFactory.CacheDirectoryGetter
com.bumptech.glide.load.engine.cache.MemoryCache
com.bumptech.glide.load.engine.cache.MemoryCache.ResourceRemovedListener
缓存架构的类关系为:
com.bumptech.glide.load.engine.cache.DiskCacheAdapter (implements com.bumptech.glide.load.engine.cache.DiskCache)
com.bumptech.glide.load.engine.cache.DiskLruCacheFactory (implements com.bumptech.glide.load.engine.cache.DiskCache.Factory)
com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory
com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper (implements com.bumptech.glide.load.engine.cache.DiskCache)
com.bumptech.glide.util.LruCache<T,Y>
com.bumptech.glide.load.engine.cache.LruResourceCache (implements com.bumptech.glide.load.engine.cache.MemoryCache)
com.bumptech.glide.load.engine.cache.MemoryCacheAdapter (implements com.bumptech.glide.load.engine.cache.MemoryCache)
com.bumptech.glide.load.engine.cache.MemorySizeCalculator
因此,可以继承
DiskLruCacheFactory或者直接实现
DiskCache.Factory接口创建自己想要的cache:
builder.setDiskCache( new DiskLruCacheFactory(getMyCacheLocationWithoutIO(), yourSizeInBytes)); // 或者 builder.setDiskCache( new DiskCache.Factory() { @Override public DiskCache build() { File cacheLocation = getMyCacheLocationBlockingIO(); cacheLocation.mkdirs(); return DiskLruCacheWrapper.get(cacheLocation, yourSizeInBytes); } });
setResizeService(ExecutorService service).
设置一个用来检索cache中没有的Resource的ExecutorService 实现。为了使缩略图请求正确工作,实现类必须把请求根据Priority优先级排好序。
setDiskCacheService(ExecutorService service).
设置一个用来检索cache中没有的Resource的ExecutorService 实现。为了使缩略图请求正确工作,实现类必须把请求根据Priority优先级排好序。
setDecodeFormat(DecodeFormat decodeFormat).
为所有的默认解码器设置解码格式。如DecodeFormat.PREFER_ARGB_8888。默认是DecodeFormat.PREFER_RGB_565,因为相对于ARGB_8888的4字节/像素可以节省一半的内存,但不支持透明度且某些图片会出现条带。
第二个方法
void registerComponents(Context context, Glide glide)。用来在Glide单例创建之后但请求发起之前注册组件,该方法每次实现只会被调用一次。通常在该方法中注册
ModelLoader。
注意:module 英[ˈmɒdju:l] 美[ˈmɑ:dʒul] 模块,model 英[ˈmɒdl] 美[ˈmɑ:dl]模型。发音很像,但要表达的意思不同,module一般指模块,而model一般指数据模型。
ModelLoader接口可以提供给我们要载入图片的View的尺寸,并允许我们通过这个尺寸选择合适的url下载一个合适尺寸的图片,使用合适大小的图片可以节省带宽和设备存储空间,也可以提升app的表现。ModelLoader可以将任意复杂的数据模型转化为具体的可被
DataFetcher使用的数据类型。该接口有两个目标:
1. 把一个具体的model转化为可解码成resource的数据类型
2. 允许与View绑定的model获取指定尺寸的resource
该接口只有一个方法
getResourceFetcher(T model, int width, int height),用来获取一个
DataFetcher(获取由model表示的resource要解码的数据),如果这个resource已经被缓存了,这个
DataFetcher就不会被使用了,如果无法创建有效的DataFetcher,将会返回
null。
使用
ModelLoader:
如果使用http或https下载图片,可以继承
ModelLoader的实现类
BaseGlideUrlLoader:
//表示resource的数据模型 public interface MyDataModel { public String buildUrl(int width, int height); } public class MyUrlLoader extends BaseGlideUrlLoader<MyDataModel> { @Override protected String getUrl(MyDataModel model, int width, int height) { // 根据不同尺寸构造不同的url return model.buildUrl(width, height); } }
之后用Glide加载图片时,用这个ModelLoader就可以了:
Glide.with(yourFragment) .using(new MyUrlLoader()) .load(yourModel) .into(yourView);
2014年Google I/O大会上的App就是用的glide,其中多尺寸图片的动态加载是这样用的:
首先服务器端要存储一张图片的全尺寸和各个尺寸的资源,可以用Bash脚本自动生成各个尺寸的图片,目录像这样:
/__w-200-400-600__/session1.jpg
/w200/session1.jpg
/w400/session1.jpg
/w600/session1.jpg
其中第一个是全尺寸的图片资源。
然后,我们App就可以根据要显示的ImageView的大小请求不同的资源了,比如我们ImageView宽300px,我们就可以请求/w400/session1.jpg,总之,请求一个最接近我们ImageView宽度的图片就行,当然不能比ImageView宽度小。实现时,利用正则表达式替换一下即可:
private static class VariableWidthImageLoader extends BaseGlideUrlLoader<String> { private static final Pattern PATTERN = Pattern.compile("__w-((?:-?\\d+)+)__"); public VariableWidthImageLoader(Context context) { super(context, urlCache); } /** * If the URL contains a special variable width indicator (eg "__w-200-400-800__") * we get the buckets from the URL (200, 400 and 800 in the example) and replace * the URL with the best bucket for the requested width (the bucket immediately * larger than the requested width). */ @Override protected String getUrl(String model, int width, int height) { Matcher m = PATTERN.matcher(model); int bestBucket = 0; if (m.find()) { String[] found = m.group(1).split("-"); for (String bucketStr : found) { bestBucket = Integer.parseInt(bucketStr); if (bestBucket >= width) { // the best bucket is the first immediately bigger than the requested width break; } } if (bestBucket > 0) { model = m.replaceFirst("w"+bestBucket); } } return model; } }
如果你不想每次请求都用
.using(new MyUrlLoader())这句话,可以在
GlideModule中进行注册:
public class MyGlideModule implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { buidler.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); } @Override public void registerComponents(Context context, Glide glide) { glide.register(MyDataModel.class, InputStream.class, new MyUrlLoader.Factory()); } }
References:
1. Norman Peitek's blog
2. Glide Wiki
相关文章推荐
- C++学习基础
- 【BZOJ-4407】于神之怒加强版 莫比乌斯反演 + 线性筛
- SPRING IN ACTION 第4版笔记-第九章Securing web applications-011-把敏感信息请求转为https(requiresChannel())
- hdu 2604 Queuing【递推+矩阵快速幂】
- 数据库设计原则
- hibernate调优
- 天猫浏览型应用的CDN静态化架构演变
- js中的正则表达式
- Entity Framework 支持 DataTable
- 版本问题和获取秘钥签名
- UNION 和UNION ALL 的区别
- leetcode 231. Power of Two
- MyBatis crud操作
- Python之异步IO&RabbitMQ&Redis
- 网易实习生真题(二叉树)
- 管道和FIFO
- js实现定时添加代码
- 数据库索引
- Android中解决scrollview中嵌套listview的listview只显示一行的问题
- bzoj3011 可并堆