关于Glide v4 使用

集成

配置

app gradle中:

repositories { mavenCentral() google() }
implementation 'com.github.bumptech.glide:glide:4.5.0' 
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'

混淆

-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule

用法

基本用法

Glide.with(fragment) .load(myUrl) .into(imageView);

自定义方法

v4特性

v4中Glide.with().load()不能配合fitCenterplaceholder使用,取而代之以一种更巧妙的方法来实现相同的功能:
annotation processor 动态生成API,允许应用修改RequestBuilderRequestOptions和任意的包含在单一流式API库中的方法
实现:

GlideApp.with(fragment) //GlideApp 是动态实现的类 后面会具体分析
  .load(myUrl)
  .placeholder(R.drawable.placeholder)
  .fitCenter()
  .into(imageView);

annotation processor:注解处理器,代替原来的APT,AOP的一种实现方式)

思考:这样设计相对于之前有什么优势?
我自己的理解是这样具有更强的拓展性:
1.对于设计者而言可以继承Glide的API实现自定义的方法
2.对于使用者而言继承Glide的API后可以实现自定义的方法

如何自定义?

实现AppGlideModule
@GlideModule
public class CustomGlideModule extends AppGlideModule {}

编译项目后查看项目结构,build下多出了四个类,这四个类正是利用annotation processor动态生成的:

image.png

这里出现了上文提到的GlideApp,查看源码可知,此类相当于Glide的代理类

GlideExtension

为了添加新的方法,修改已有的方法或者添加对其他类型格式的支持,我们需要在拓展中使用加了注解的静态方法
GlideOption用来添加自定义的方法,GlideType用来支持新的格式

GlideOption

新建CustomGlideExtension:

@GlideExtension
public class CustomGlideExtension {
    //缩略图的最小尺寸,单位:px
    private static final int MINI_THUMB_SIZE = 100;

    /**
    * 将构造方法设为私有,作为工具类使用
    */
    private CustomGlideExtension() {
    }

    /**
    * 1.自己新增的方法的第一个参数必须是RequestOptions options
    * 2.方法必须是静态的
    * @param options
    */
    @GlideOption
    public static void miniThumb(RequestOptions options) {
        options
                .fitCenter()
                .override(MINI_THUMB_SIZE);
    }
}

编译工程,打开build目录中的GlideOptions,可以看见自动生成了两个方法:

/**
* @see CustomGlideExtension#miniThumb(RequestOptions)
*/
@NonNull
@CheckResult
public GlideOptions miniThumb() {
if (isAutoCloneEnabled()) {
return clone().miniThumb();
}
CustomGlideExtension.miniThumb(this);
return this;
}

/**
* @see CustomGlideExtension#miniThumb(RequestOptions)
*/
@CheckResult
public static GlideOptions miniThumbOf() {
return new GlideOptions().miniThumb();
}

使用以上自定义的方法:

GlideApp.with(fragment)
  .load(url)
  .miniThumb(thumbnailSize)
  .into(imageView);
GlideType

以对GIF格式的支持为例(实际上Glide的API中已经实现)
在刚才的CustomGlideExtension类中加上:

@GlideExtension
public class CustomGlideExtension {

    private static final RequestOptions DECODE_TYPE_GIF = GlideOptions.decodeTypeOf(GifDrawable.class).lock();

    @GlideType(GifDrawable.class)
    public static void asGIF(RequestBuilder requestBuilder) {
        requestBuilder
                .transition(new DrawableTransitionOptions())
                .apply(DECODE_TYPE_GIF);
    }
}

编译工程,打开build目录中的GlideRequests

/**
* @see CustomGlideExtension#asGIF(RequestBuilder)
*/
@NonNull
@CheckResult
public GlideRequest asGIF() {
GlideRequest requestBuilder = this.as(GifDrawable.class);
CustomGlideExtension.asGIF(requestBuilder);
return requestBuilder;
}

使用:

GlideApp.with(this)
       .asGIF()
       .load(url)
       .into(iv_test1);

占位图

三种占位图:

  • Placeholder 请求图片加载中
  • Error 请求图片加载错误
  • Fallback 请求url/model为空

Options

RequestOptions

Glide中的大多请求参数都可以通过RequestOptions类和apply()方法来设置
Glide中的请求参数主要有:

  • Placeholders 占位符
  • Transformations 变换
  • Caching Strategies 缓存策略
  • 组件特定参数:编码质量,解码参数等

将图片设置为CenterCrop:

import static com.bumptech.glide.request.RequestOptions.centerCropTransform;

Glide.with(fragment)
    .load(url)
    .apply(centerCropTransform(context))
    .into(imageView);

:其实Glide会自动根据layout文件中设置的属性设置图片的显示方式 所以在layout文件中设置ImageViewandroid:scaleType="centerCrop"可以达到相同的效果

TransitionOptions

TransitionOptions决定图片加载完成如何从占位图(或者之前的图片)过渡
三种过度方式:

  • 淡入

  • 交叉淡入

  • 不过渡

Glide.with(fragment)
    .load(url)
    .transition(DrawableTransitionOptions.withCrossFade())
    .into(view);

RequestBuilder

作用:

  • 指定加载类型。asBitmap()、asGif()、asDrawable()、asFile()
  • 指定要加载url/model
  • 指定要加载到那个View
  • 指定要应用的RequestOption
  • 指定要应用的TransitionOption
  • 指定要加载的缩略图

获取RequestBuilder:

RequestBuilder requestBuilder = Glide.with(fragment);

默认得到一个Drawable RequestBuilder,,如果要指定类型为Bitmap,可以这样写:

RequestBuilder requestBuilder = Glide.with(fragment).asBitmap();

应用RequestOptions:

RequestBuilder requestBuilder = Glide.with(fragment);
requestBuilder.apply(requestOptions);
requestBuilder.transition(transitionOptions);

Transformations

Glide会自动读取ImageView的缩放类型,所以一般在layout文件指定scaleType即可
CenterCrop, CenterInside,CircleCrop , FitCenter, RoundedCorners
三种用法:

  • 使用RequestOptions
RequestOptions options = new RequestOptions();
options.centerCrop();

Glide.with(fragment)
    .load(url)
    .apply(options)
    .into(imageView);
  • 使用RequestOptions中的transform方法
Glide.with(fragment)
    .load(url)
    .apply(RequestOptions.fitCenterTransform())
    .into(imageView);
  • V4特性 (推荐)
GlideApp.with(fragment)
  .load(url)
  .fitCenter()
  .into(imageView);

Transitions(动画)

普通动画

过渡动画是指占位图到请求图片或者缩略图到完整图片的动画 过渡动画只能针对单一请求 不能跨请求
执行时机:

  • 图片在磁盘缓存
  • 图片在本地
  • 图片在远程

默认图片在内存缓存上是不会执行过渡动画
在内存缓存上加载动画:

GlideApp.with(this).load(R.drawable.img_default).listener(new RequestListener(){

    @Override
    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
        return false;
    }

    @Override
    public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
        if (dataSource == DataSource.MEMORY_CACHE) {
            //当图片位于内存缓存时,glide默认不会加载动画
            imageView.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in));
        }
        return false;
    }
}).fitCenter().transition(GenericTransitionOptions.with(R.anim.fade_in)).into(imageView);

常规用法:

Glide.with(fragment)
    .load(url)
    .transition(DrawableTransitionOptions.withCrossFade())
    .into(view);

三种TransitionOptions:

  • GenericTransitionOptions 通用型
  • DrawableTransitionOptions
  • BitmapTransitionOptions

使用自定义动画:
GenericTransitionOptions.with(int viewAnimationId)或者BitmapTransitionOptions.withCrossFade(int animationId, int duration)或者DrawableTransitionOptions.withCrossFade(int animationId, int duration)
处于性能考虑,不要在ListView,GridView,RecycleView中使用过渡动画,
TransitionOptions.dontTransition()或者dontAnimate 不加载动画

自定义过渡动画

1.实现TransitionFactory
2.重写build()
可以控制图片在内存缓存上是否执行动画

基本配置

配置内存缓存

Glide会自动合理分配内存缓存,也可以手动分配
三种方法

  • 通过MemorySizeCalculator设置
@GlideModule
public class CustomGlideModule extends AppGlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
                .setMemoryCacheScreens(2) //设置缓存多少屏图片
                .build();
        builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
    }
}
  • 手动定义大小
@GlideModule
public class CustomGlideModule extends AppGlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
        builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
    }
}
  • 自己实现MemoryCache接口
@GlideModulepublicclass YourAppGlideModule extends AppGlideModule {@OverridepublicvoidapplyOptions(Context context, GlideBuilder builder) {
    builder.setMemoryCache(new CustomGlideMemoryCache());
  }
}

清除内存缓存(需要在主线程中调用):

GlideApp.get(context).clearMemory();

跳过内存缓存:

GlideApp.with(getActivity())
        .load(url)
        .skipMemoryCache(true)
        .dontAnimate()
        .centerCrop()
        .into(imageView);

磁盘缓存

Glide使用DiskLruCacheWrapper作为默认的磁盘缓存:

@GlideModule
public class CustomGlideModule extends AppGlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MB
        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
//        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "cacheFolderName", diskCacheSizeBytes));
//        builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));
    }
}

以上 指定内部缓存还是外部缓存 指定缓存的大小和文件夹
自定义磁盘缓存:自己实现DiskCache接口
清除磁盘缓存(主线程中调用):

GlideApp.get(context).clearDiskCache();

设置磁盘缓存策略:

GlideApp.with(getActivity())
        .load(url)
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .dontAnimate()
        .centerCrop()
        .into(imageView);

默认的策略:DiskCacheStrategy.AUTOMATIC
DiskCacheStrategy五个常量:

  • DiskCacheStrategy.ALL使用DATARESOURCE缓存远程数据,仅使用RESOURCE来缓存本地数据
  • DiskCacheStrategy.NONE 不使用磁盘缓存
  • DiskCacheStrategy.DATA 在资源解码前就将原始数据写入磁盘缓存
  • DiskCacheStrategy.RESOURCE 在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源
    -DiskCacheStrategy.AUTOMATIC 根据原始图片数据和资源编码策略来自动选择磁盘缓存策略

禁止解析manifest文件

主要针对v3升级到v4 可以提升初始化速度 避免一些潜在错误

@GlideModule
public class CustomGlideModule extends AppGlideModule {
  @Override
  public boolean isManifestParsingEnabled() {
    return false;
  }
}

View尺寸

Glide对Imageviewwidthheight属性的解析逻辑:

  • 如果widthheight都大于0,则使用layout中的尺寸。

  • 如果widthheight都是WRAP_CONTENT,则使用屏幕尺寸。

  • 如果widthheight中至少有一个值<=0并且不是WRAP_CONTENT,那么就会在布局的时候添加一个OnPreDrawListener监听ImageView的尺寸

Glide对WRAP_CONTENT支持不好 尽量不用

运行时修改ImageView尺寸两种方法:

  • 继承ImageViewTarget
public class CustomImageViewTarget extends ImageViewTarget {

        private int width, height;

        public CustomImageViewTarget(ImageView view) {
            super(view);
        }

        public CustomImageViewTarget(ImageView view, int width, int height) {
            super(view);
            this.width = width;
            this.height = height;
        }

        @Override
        public void onResourceReady(Bitmap bitmap, Transition transition) {
            super.onResourceReady(bitmap,transition);
        }

        @Override
        protected void setResource(@Nullable Bitmap resource) {
            view.setImageBitmap(resource);
        }

        @Override
        public void getSize(SizeReadyCallback cb) {
            if (width > 0 && height > 0) {
                cb.onSizeReady(width, height);
                return;
            }
            super.getSize(cb);
        }
    }

GlideApp.with(context)
        .asBitmap()
        .load(url)
        .dontAnimate()
        .placeholder(R.drawable.img_default)
        .into(new CustomImageViewTarget(imageview, 300, 300));
  • override()
GlideApp.with(mContext)
    .load(url)
    .override(width,height)
    .into(view);

你可能感兴趣的:(关于Glide v4 使用)