美文网首页
关于Glide v4 使用

关于Glide v4 使用

作者: 34sir | 来源:发表于2018-02-07 17:44 被阅读351次

    集成

    配置

    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<GifDrawable> requestBuilder) {
            requestBuilder
                    .transition(new DrawableTransitionOptions())
                    .apply(DECODE_TYPE_GIF);
        }
    }
    

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

    /**
    * @see CustomGlideExtension#asGIF(RequestBuilder)
    */
    @NonNull
    @CheckResult
    public GlideRequest<GifDrawable> asGIF() {
    GlideRequest<GifDrawable> 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<Drawable> requestBuilder = Glide.with(fragment);
    

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

    RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();
    

    应用RequestOptions:

    RequestBuilder<Drawable> 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<Bitmap> {
    
            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<? super Bitmap> 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 使用

          本文链接:https://www.haomeiwen.com/subject/vxeazxtx.html