Glide配置:AppGlideModule

Quibbler 2020-11-21 2111

Glide配置:AppGlideModule


        Glide用起来非常方便,基本用法见Glide的基本用法,简短的一句链式调用就能给ImageView设置图片。而且自带缓存实现,如果不进行额外的设置Glide的缓存目录、缓存大小都是默认的。应用可以自行进行定制修改,就用到AppGlideModule



1、自定义AppGlideModule

        配置Glide加载图片的设置、缓存设置、缓存策略,就需要应用自己继承AppGlideModule类,实现里面的空方法:

    public class ApplicationGlideModule extends AppGlideModule {
        @Override
        public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
            super.applyOptions(context, builder);
        }
        @Override
        public boolean isManifestParsingEnabled() {
            return super.isManifestParsingEnabled();
        }
    }

        


2、GlideBuilder

        applyOptions(Context context,GlideBuilder builder)方法就是我们需要关注的,传入的GlideBuilder类型参数,典型的创建者模式,用来创建Glide实例(Glide是单例的)。其中有非常多的配置项:

  /** A builder class for setting default structural classes for Glide to use. */
  @SuppressWarnings("PMD.ImmutableField")
  public final class GlideBuilder {
    private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
    private Engine engine;
    private BitmapPool bitmapPool;
    private ArrayPool arrayPool;
    private MemoryCache memoryCache;
    private GlideExecutor sourceExecutor;
    private GlideExecutor diskCacheExecutor;
    private DiskCache.Factory diskCacheFactory;
    private MemorySizeCalculator memorySizeCalculator;
    private ConnectivityMonitorFactory connectivityMonitorFactory;
    ...
  }

        如果应用不进行设置,Glide会全部使用默认配置去创建Glide实例:

  Glide build(@NonNull Context context) {
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }
    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled,
        isImageDecoderEnabledForBitmaps);
  }


2.1、设置Bitmap缓冲池

        setBitmapPool(BitmapPool bitmapPool):Bitmap对象复用缓冲池

    //设置Bitmap缓冲池大小32Mb
    builder.setBitmapPool(new LruBitmapPool(1024 * 1024 * 32));

        开发者可以实现BitmapPool接口,实现自己的Bitmap缓冲池。默认的LruBitmapPool实现已经非常优秀!

/** An interface for a pool that allows users to reuse {@link android.graphics.Bitmap} objects. */
public interface BitmapPool {
  ...
}


2.2、设置内存缓存

        setMemoryCache(MemoryCache memoryCache):设置内存缓存

    builder.setMemoryCache(new LruResourceCache(32 * 1024 * 1024));

        同样可以实现MemoryCache接口,自定义内存缓存。不过Glide自带的LruResourceCache已经足够优秀。

  /** An interface for adding and removing resources from an in memory cache. */
  public interface MemoryCache {
    ...
  }


2.3、配置磁盘缓存

        setDiskCache(DiskCache.Factory diskCacheFactory)

    builder.setDiskCache(new DiskLruCacheFactory("image", 32 * 1024 * 1024));

        DiskCache.Factory接口定义如下,Glide磁盘缓存默认存储在私有data/data/包名/cache/image_manager_disk_cache目录下,250Mb的缓存。

  /** An interface for lazily creating a disk cache. */
  interface Factory {
    /** 250 MB of cache. */
    int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;
    String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
    ...
  }

        有几个默认的实现,一个是内部存储缓存InternalCacheDiskCacheFactory

    //设置128Mb的磁盘缓存大小,目录名仍使用默认的
    builder.setDiskCache(new InternalCacheDiskCacheFactory(context, 128 * 1024 * 1024));

        另一个是外部磁盘缓存ExternalCacheDiskCacheFactory。不过已经废弃,从Android 11开始建议使用私有目录。

    builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, 128 * 1024 * 1024));


2.4、配置图片加载选项

        setDefaultRequestOptions(final RequestOptions requestOptions)

    RoundedCorners roundedCorners = new RoundedCorners(6);
    RequestOptions requestOptions = RequestOptions.bitmapTransform(roundedCorners);

        构造一个RequestOptions对象,进行各种设置,加载图片的时候使用这个默认的。不用每次使用Glide加载图片开始with()...的时候单独再设置。

    builder.setDefaultRequestOptions(requestOptions
            .format(DecodeFormat.PREFER_ARGB_8888)
            .diskCacheStrategyOf(DiskCacheStrategy.RESOURCE)
            .skipMemoryCache(false)
            .encodeQuality(50));


2.5、线程执行器

        应用线程过多在性能和耗电上是一个大问题。曾在知乎上看到一篇文章支付宝峰值线程数量高达300多条。Glide内部有自己的线程池实现,如果不设置线程池,Glide会创建自己的线程执行器。

        当然最好可以使用应用公用的线程池:

        setDiskCacheExecutor(GlideExecutor service)

        setSourceExecutor(GlideExecutor service)

        setAnimationExecutor(GlideExecutor service)



3、组件注册

        自定义好应用的组件如何注册给Glide使之生效呢?


3.1、AndroidManifest中注册

        在androidmanifest.xml中的<application />节点下添加<meta-data />,关于Meta Data详见Android meta-data用法

    <application>
    
        <meta-data
            android:name="com.quibbler.news.ApplicationGlideModule"
            android:value="AppGlideModule" />
            
    </application>

        Glide在创建的时候会去加载AndroidManifest中的配置(以后有空分析一下这里解析的原理)isManifestParsingEnabled()方法的默认实现就是true

  /**
   * Returns {@code true} if Glide should check the AndroidManifest for {@link GlideModule}s.
   *
   * <p>Implementations should return {@code false} after they and their dependencies have migrated
   * to Glide's annotation processor.
   *
   * <p>Returns {@code true} by default.
   */
  public boolean isManifestParsingEnabled() {
    return true;
  }


3.2、@GlideModule注解

        在自定义的AppGlideModule类上加上@GlideModule注解

    import com.bumptech.glide.annotation.GlideModule;
    
    @GlideModule
    public class ApplicationGlideModule extends AppGlideModule {
        ...
    }

        不过别忘了,需要在build.gradle中添加Glide专门的annotationProcessor注解处理器

    //Glide
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

        同时需要重写isManifestParsingEnabled()方法,返回false,不需要解析AndroidManifest中的配置,有利于提高Glide初始化速度

    @Override
    public boolean isManifestParsingEnabled() {
        return false;
    }



4、注意

        ①自定义的AppGlideModule需要在app/proguard-rules.pro混淆配置文件中配置避免被混淆,以免Glide加载模块出现问题。

-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class * extends com.bumptech.glide.module.AppGlideModule {
 <init>(...);
}

        ②APP应用只能定义一个AppGlideModule模块,超过一个会在编译时报错。aar库应用不能实现AppGlideModule,需要使用LibraryGlideModules。



参考资料:

        最全Glide 配置、缓存

        Glide配置和自定义模块

        最简Glide4.8.0配置

        Glide缓存配置

        Glide中的缓存

        Android-Glide配置介绍

        

不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com