Glide配置

懒加载配置

从Glide3.5开始,你可以使用GlideModule接口来懒加载配置Glide以及注册组件(如ModelLoaders),这些配置将会在第一个Glide请求发起的时候被调用。

创建一个GlideModule

为了使用和注册GlideModule,首先需要实现该接口,加入你的配置和组件。

package com.mypackage;

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.
    }
}

然后,添加你的实现类到proguard.cfg文件中,让你的module可以被反射调用到。这个性能开支很少,因为每个module只会在Glide第一次请求的时候实例化一次。

-keepnames class com.mypackage.MyGlideModule
# or more generally:
#-keep public class * implements com.bumptech.glide.module.GlideModule

最后,添加meta-data标记到AndroidManifest.xml,那样Glide才能找到它。

<manifest ...>
    <!-- ... permissions -->
    <application ...>
        <meta-data
            android:name="com.mypackage.MyGlideModule"
            android:value="GlideModule" />
        <!-- ... activities and other components -->
    </application>
</manifest>

你可以实现任意个GlideModule,但是每一个都要添加到proguard.cfg,而且每一个GlideModule都要在manifest有自己的meta-data标记。

Library工程

Library工程可能含有一个或多个GlideModule。当我们使用Gradle(或者任何支持manifest合并的构建工具)构建app时,如果我们所依赖的Library工程的manifest中含有module,那么这些module会自动并入到app中。如果构建工具不支持manifest合并,那么这些library工程中的module必须手动添加到你app的manifest中。

GlideModule冲突

虽然Glide允许每个app注册多个Glidemodule,但是不会以某种特定的顺序调用这些module。所以,如果你的app中多个GlideModules或者依赖的library工程中有多个GlideModules,你必须负责避免他们之间的冲突。 如果冲突不可避免,app应该定义自己的默认module,这个module需要手动解决这些冲突,提供所有Library工程所需要的依赖。使用Gradle的开发者,或者使用manifest合并的开发者,可以通过下面的标签来排除冲突的module。

<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”remove” />

全局配置

你可以配置一些作用于所有请求的全局性配置项。请使用GlideModule#applyOptions方法中(注:作为参数)提供给你的GlideBuilder来配置。本节代码示例中的builder就是一个GlideModule对象。

磁盘缓存

你可以使用GlideBuildersetDiskCache()方法设置磁盘缓存的位置、大小(最大值)。你也可以使用DiskCacheAdapter彻底关闭缓存,或者自己实现DiskCache接口来换掉默认实现。磁盘缓存由DiskCache.Factory接口的实例在后台线程中创建,使用后台线程可以避免在严格模式中出现问题。 Glide默认使用InternalCacheDiskCacheFactory类建立磁盘缓存。这个内部缓存工厂(internal cache factory)会把磁盘缓存放到应用程序的内部缓存目录中,并且设置最大空间是250MB,使用内部缓存的目录而不是SD卡的外部目录意味着其他应用程序无法访问到你下载的图片。具体请查看Android的存储选项相关文档

大小

使用InternalCacheDiskCacheFactory设置磁盘缓存大小

builder.setDiskCache(
  new InternalCacheDiskCacheFactory(context, yourSizeInBytes));

位置

也可以设置磁盘缓存位置 你可以使用InternalCacheDiskCacheFactory来把你的磁盘缓存放到应用程序私有的内部存储目录中:

builder.setDiskCache(
  new InternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));

还可以用ExternalCacheDiskCacheFactory来把你的磁盘缓存放到sd卡的公共缓存目录上。

builder.setDiskCache(
  new ExternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));

如果你想用其他自定义的路径,可以用DiskLruCacheFactory类的构造函数来实现。

// If you can figure out the folder without I/O:
// Calling Context and Environment class methods usually do I/O.
builder.setDiskCache(
  new DiskLruCacheFactory(getMyCacheLocationWithoutIO(), yourSizeInBytes));

// In case you want to specify a cache folder ("glide"):
builder.setDiskCache(
  new DiskLruCacheFactory(getMyCacheLocationWithoutIO(), "glide", yourSizeInBytes));

// In case you need to query the file system while determining the folder:
builder.setDiskCache(new DiskLruCacheFactory(new CacheDirectoryGetter() {
    @Override public File getCacheDirectory() {
        return getMyCacheLocationBlockingIO();
    }
}), yourSizeInBytes);

注意:请牢记,写死任何值都不是个好主意,尤其是目录的路径,因为自Android4.2开始,支持单设备多用户。

如果你想完全控制缓存的创建,可以自己实现DiskCache.Factory接口,使用DiskLruCacheWrapper可以在你想要的位置创建一个新的缓存。

builder.setDiskCache(new DiskCache.Factory() {
    @Override public DiskCache build() {
        File cacheLocation = getMyCacheLocationBlockingIO();
        cacheLocation.mkdirs();
        return DiskLruCacheWrapper.get(cacheLocation, yourSizeInBytes);
    }
});

内存缓存和缓存池

GlideBuilder类允许你设置内存缓存大小,而且可以实现自定义的MemoryCacheBitmapPool

大小

默认大小是由MemorySizeCalculator类决定的。MemorySizeCalculator类会考虑该设备的屏幕大小、可用内存来计算出一个合理的默认值。如果你想调整这个默认值,请构建自己的实例。

MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();

如果你想在应用的某个阶段动态调整Glide的内存占用,你可以选择一个MemoryCategory并使用setMemoryCategory()方法传入Glide中:

Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);

内存缓存

Glide的内存缓存会在内存中持有资源,它的作用是,我们可以不进行IO操作而快速获得可用资源。 你可以使用GlideBuildersetMemoryCache()方法设置大小,或者设置你关于内存缓存的自定义实现(自定义类)。LruResourceCache类是Glide的默认实现。你可以通过LruResourceCache的构造函数来配置内存占用的bytes的最大值。

builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));

Bitmap池

Glide的Bitmap池主要作用是,可以让各种尺寸的Bitmap被复用,可以可观地减少由垃圾回收引起的内存抖动。在解码图片时,需要给像素数组分配空间,这会触发垃圾回收。 你可以使用GlideBuildersetBitmapPool()方法设置大小,或者设置你关于Bitmap池的自定义实现,LruBitmapPool类是Glide的默认实现。LruBitmapPool类使用了LRU算法维护最近最常使用的Bitmap的尺寸。你可以通过LruBitmapPool的构造函数配置内存占用的bytes的最大值。

builder.setBitmapPool(new LruBitmapPool(sizeInBytes));

Bitmap格式

GlideBuilder 类也允许你配置一个App全局使用的Bitmap的Config属性。 Glide默认使用RGB_565,因为它每个像素只需要2bytes(16bit)的空间,它仅需要高质量图片(既系统默认的ARGB_8888)一半的内存空间。但是,这对于某些图片这可能会出现『条带』的问题,而且它也不支持透明度。 如果在你的应用中『条带』是一个重要的问题,或者你需要尽可能好的图片质量,你可以使用GlideBuildersetDecodeFormat方法设置DecodeFormat.ALWAYS_ARGB_8888作为首选配置。

builder.setDecodeFormat(DecodeFormat.ALWAYS_ARGB_8888);