Glide介绍及基本使用方法

官方介绍

关于 Glide

Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。

Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。

虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。

性能

Glide 充分考虑了Android图片加载性能的两个关键方面:

  • 图片解码速度
  • 解码图片带来的资源压力

为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。

Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:

  • 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
  • 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
  • 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

环境配置

Gradle依赖

在gradle里依赖,目前最新版本为4.12.0

implementation 'com.git`hub.bumptech.glide:glide:4.12.0'`

Glide 支持 Maven 项目,依赖方法:

<dependency>
<groupId>com.github.bumptech.glide</groupId>
<artifactId>glide</artifactId>
<version>4.12.0</version>
<type>aar</type>
</dependency>

AndroidManifest.xml 中添加权限设置

按项目需求进行添加

    <!-- 网络权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     
    <!-- 读取权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     
    <!-- 写入权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

基本用法

Glide 库是使用流接口(fluent interface)。对一个完整的功能请求,Glide 建造者要求最少有三个参数。

//加载图片
Glide.with(context)
    .load(url)
    .into(imageView);

//取消加载
Glide.with(context).clear(imageView);

context :可以传入fragment 、activity 和applicationContext 等。
load :图片资源。可以是resourceId 、url 、uri 、drawable 、file 等。
into :图片会显示到对应的 ImageView 中

取消加载并非是必要的操作,在Glide.with()中传入的context如果是activity或fragment,当它们的实例销毁时,Glide 会自动取消加载并回收资源。

小拓展:
resourceID转换为Uri的方法

private static Uri resourceIdToUri(Context context, int resourceId) {
    return Uri.parse("android.resource://" + context.getPackageName()
     + "/" + resourceId);
}

占位符

Glide允许用户指定三种不同类型的占位符,分别在三种不同场景使用。他们分别是placeholder,error和falllback。

placeholder(占位符)

占位符是当请求正在执行时被展示的 Drawable 。当请求成功完成时,占位符会被请求到的资源替换。

Glide.with(context)
  .load(url)
  .placeholder(R.drawable.placeholder)
  .into(view);

error(错误符)

error Drawable 在请求永久性失败时展示。
error()接受的参数只能是已经初始化的 drawable 对象或者指明它的资源(R.drawable.xxx)

Glide.with(context)
  .load(url)
  .error(R.drawable.error)
  .into(view);

fallback(后备回调符)

fallback Drawable 在请求的url为 null 时展示。

Glide.with(context)
  .load(url)
  .fallback(R.drawable.fallback)
  .into(view);

当Gilde.load()中传入的资源为null,或者是无法成功获取时,展示优先级为fallback > error > placeholder。
占位符都是独立的,可以根据开发需要来调用。除基本用法中的三个方法,Glide的其他方法也是如此。
占位符是在主线程从Android Resources加载的。占位符应当比较小且容易被系统资源缓存机制缓存起来。

提示:多个不同的View上可以使用相同的Drawable,但仅限于无状态的drawable(例如Bitmap)。但是有状态的 Drawable 不一样,在同一时间多个 View 上展示它们通常不是很安全,因为多个View会立刻修改(mutate) Drawable 。对于有状态的 Drawable ,建议传入一个资源ID,或者使用 newDrawable() 来给每个请求传入一个新的拷贝。


选项

请求选项

Glide中的大部分设置项都可以直接应用在 Glide.with() 返回的 RequestBuilder 对象上。

可用的选项包括但不限于:

  • 占位符(Placeholders)
  • 转换(Transformations)
  • 缓存策略(Caching Strategies)
  • 组件特有的设置项,例如编码质量,或Bitmap的解码配置等。

如果想让应用的不同部分之间共享相同的加载选项,可以初始化一个新的 RequestOptions 对象,并在每次加载时通过 apply() 方法传入这个对象:

RequestOptions cropOptions = new RequestOptions().centerCrop(context);

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

apply() 方法可以被调用多次,因此 RequestOption 可以被组合使用。如果 RequestOptions 对象之间存在相互冲突的设置,那么只有最后一个被应用的 RequestOptions 会生效。

过渡选项

TransitionOptions 用于决定加载完成时会发生什么。

使用 TransitionOption 可以应用以下变换:

  • View淡入
  • 与占位符交叉淡入
  • 或者什么都不发生

如果不使用变换,你图像将会直接出现在其显示位置,替换掉之前的图像。为了避免这种突然的改变,可以淡入view,或者让多个Drawable交叉淡入,而这些都需要使用TransitionOptions完成。

例如,要应用一个交叉淡入变换:

import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
//import com.bumptech.glide.GenericTransitionOptions.withNoTransition

Glide.with(fragment)
    .load(url)
    .transition(withCrossFade())
//    不发生变换
//    .transition(withNoTransition())
    .into(view);

不同于RequestOptions,TransitionOptions是特定资源类型独有的,假如请求加载一个 Bitmap ,需要使用 BitmapTransitionOptions ,而不是 DrawableTransitionOptions 。

RequestBuilder

使用 RequestBuilder 可以指定:

  • 加载的资源类型(Bitmap, Drawable, 或其他)
  • 加载的资源地址(url/model)
  • 最终加载到的View
  • 想应用的(一个或多个)RequestOption 对象
  • 想应用的(一个或多个)TransitionOption 对象
  • 想加载的缩略图 thumbnail()
    要构造一个 RequestBuilder 对象,可以通过先调用 Glide.with()然后再调用某一个 as 方法来完成:
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();

或先调用 Glide.with() 然后 load():

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).load(url);
选择资源类型

RequestBuilders 是特定于它们将要加载的资源类型的。默认情况下会得到一个 Drawable RequestBuilder ,但可以使用 as… 方法来改变请求类型。

应用 RequestOptions

前面提到,可以使用 apply() 方法应用 RequestOptions ,使用 transition() 方法应用 TransitionOptions 。

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
  requestBuilder.apply(requestOptions);
  requestBuilder.transition(transitionOptions);
缩略图 (Thumbnail) 请求

Glide 的 thumbnail() API 允许指定一个 RequestBuilder 以与你的主请求并行启动。
thumbnail() 会在主请求加载过程中展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。thumbnail() API 允许简单快速地加载图像的低分辨率版本,并且同时加载图像的无损版本。

Glide.with(context)
  .load(url)
  .thumbnail(Glide.with(context).load(thumbnailUrl))
  .into(imageView);

在只有url而没有thumbnailUrl的情况下,可以使用override方法。

Glide.with(context)
  .load(url)
  .thumbnail(Glide.with(context)
    .load(url)
//    .override(int width, int height)
    .override(int thumbnailSize))
  .into(view);

thumbnail() 方法有一个简化版本,它只需要一个 sizeMultiplier 参数

Glide.with(context)
  .load(url)
  .thumbnail(/*sizeMultiplier=*/ 0.1f)
  .into(imageView);
在失败时开始新的请求

在 error 方法里 来指定一个 RequestBuilder,可以在主请求失败时开始一次新的加载。

Glide.with(context)
  .load(primaryUrl)
  .error(Glide.with(context)
      .load(fallbackUrl))
  .into(imageView);

如果主请求成功完成,这个error里的RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail() 和一个 error() RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。

请求的优先级

Priority枚举给了四个不同的选项,下面是按照递增priority(优先级)的列表:

Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE

优先级并不是完全严格遵守的。Glide 将会用他们作为一个准则,并尽可能的处理这些请求,但是它不能保证所有的图片都会按照所要求的顺序加载。

Glide.with(context)
  .load(url)
  .priority(Priority.HIGH)
  .into(imageView);

组件选项

Option 类是给Glide的组件添加参数的通用办法,包括 ModelLoaders , ResourceDecoders , ResourceEncoders , Encoders 等等。一些Glide的内置组件提供了设置项,自定义的组件也可以添加设置项。

Option 通过 RequestOptions 类应用到请求上:

Glide.with(context)
  .load(url)
  .option(MyCustomModelLoader.TIMEOUT_MS, 1000L)
  .into(imageView);

变换

在Glide中,Transformations 可以获取资源并修改它,然后返回被修改后的资源。通常变换操作是用来完成剪裁或对位图应用过滤器,但它也可以用于转换GIF动画,甚至自定义的资源类型。

内置类型

Glide 提供了很多内置的变换,包括:

  • CenterCrop
  • FitCenter
  • CircleCrop

应用

CenterCrop

CenterCrop()是一个裁剪技术,即缩放图像让它填充到 ImageView 界限内并且裁剪额外的部分。ImageView 可能会完全填充,但图像可能不会完整显示。

Glide.with(context)
  .load(url)
  .centerCrop()
  .into(imageView)

或使用 RequestOptions

RequestOptions options = new RequestOptions();
options.centerCrop();

Glide.with(context)
    .load(url)
    .apply(options)
    .into(imageView);
FitCenter

fitCenter() ,即缩放图像让图像都测量出来等于或小于 ImageView 的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。

Glide.with(context)
  .load(url)
  .fitCenter()
  .into(imageView)
CircleCrop

CircleCrop()和fitCenter()行为类型,但会剪裁出圆形图片。

Glide.with(context)
  .load(url)
  .circleCrop()
  .into(imageView)

Transformations

添加依赖

compile 'jp.wasabeef:glide-transformations:4.0.0'
//使用GPU转换
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:xxxx'

多重变换

默认情况下,每个 transform() 调用,或任何特定转换方法的调用都会替换掉之前的变换。

如果想在单次加载中应用多个变换,请使用 MultiTransformation 类,或其快捷方法 .transforms() 。

Glide.with(context)
  .load(url)
//   MultiTransformation 类
//  .transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())

// 快捷方法
  .transform(new FitCenter(), new YourCustomTransformation())
  .into(imageView);

向 MultiTransformation 的构造器传入变换参数的顺序,决定了这些变换的应用顺序。

自定义变换

一个简单的BitmapTransformation

如果只需要变换 Bitmap,最好是从继承 BitmapTransformation 开始。BitmapTransformation 为我们处理了一些基础的东西,例如,如果变换返回了一个新修改的 Bitmap ,BitmapTransformation将负责提取和回收原始的 Bitmap。

public class FillSpace extends BitmapTransformation {
    private static final String ID = "com.bumptech.glide.transformations.FillSpace";
    private static final String ID_BYTES = ID.getBytes(STRING_CHARSET_NAME);

    @Override
    public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {
            return toTransform;
        }

        return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, /*filter=*/ true);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest)
        throws UnsupportedEncodingException {
      messageDigest.update(ID_BYTES);
    }
    
    @Override
    public void equals(Object o) {
      return o instanceof FillSpace;
    }

    @Override
    public int hashCode() {
      return ID.hashCode();
    } 
}
使用这个BitmapTransformation

Glide 有两种方式去使用转换。首先是传一个类的实例作为参数给 .transform()。这里可以使用任何转换,无论它是否是用于图像还是 Gif。其他选择是使用 .bitmapTransform(),它只能用于 bitmap 的转换。因为我们上面的实现是为 bitmap 设计的,这两者我们都可以用:

Glide  
    .with(context)
    .load(url)
    .transform(new FillSpace())
    //.bitmapTransform(new FillSpace()) // this would work too!
    .into( imageView );
注意

请特别注意,对于任何 Transformation 子类,包括 BitmapTransformation,有三个方法 必须 实现它们,以使得磁盘和内存缓存正确地工作。如果没有复写equals()和hashCode(),BitmapTransformation 和 Transformation 也能通过编译,但这并不意味着它们能正常工作。

ImageView的自动变换

在Glide中,当一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。如果 scaleType 是 CENTER_CROP , Glide 将会自动应用 CenterCrop 变换。如果 scaleType 为 FIT_CENTER 或 CENTER_INSIDE ,Glide会自动使用 FitCenter 变换。

我们可以覆写默认的变换,只需要一个带有 Transformation 集合的 RequestOptions 即可。另外也可以通过使用 dontTransform() 确保不会自动应用任何变换。


目标

关于Target

在Glide中,Target 是介于请求和请求者之间的中介者的角色。Target 负责展示占位符,加载资源,并为每个请求决定合适的尺寸。被使用得最频繁的是 ImageViewTargets ,它用于在 ImageView 上展示占位符、Drawable 和 Bitmap 。

指定目标

into(Target) 方法不仅仅用于启动每个请求,它同时也指定了接收请求结果的 Target:

Target<Drawable> target = 
  Glide.with(context)
    .load(url)
    .into(new Target<Drawable>() {
      ...
    });

Glide 提供了一个辅助方法 into(ImageView) ,它接受一个 ImageView 参数并为其请求的资源类型包装了一个合适的 ImageViewTarget:

Target<Drawable> target = 
  Glide.with(context)
    .load(url)
    .into(imageView);

取消和重用

into(Target) 和 into(ImageView) 都返回了一个 Target 实例。重用这个 Target 来在将来开始一个新的加载,之前开始的任何请求都会被取消,它们使用的资源将被释放。
也可以使用返回的 Target 来 clear() 之前的加载,这将在不需要开始新的加载的情况下释放掉相关资源。

Target<Drawable> target = 
  Glide.with(fragment)
    .load(url)
    .into(new Target<Drawable>() {
      ...
    });
... 
// Some time in the future:
Glide.with(context)
  .load(newUrl)
  .into(target);
  
// Some time in the future:
Glide.with(context).clear(target);

//与加载到imageView类似
Glide.with(context)
  .load(newUrl)
  .into(imageView);
Glide.with(context).clear(imageView);

SimpleTarget

指定尺寸
SimpleTarget target = new SimpleTarget<Bitmap>( 250, 250 ) {  
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        imageView.setImageBitmap( bitmap );
    }
};

 Glide.with( context.getApplicationContext() ) // safer!
      .load( url )
      .asBitmap()
      .into( target );

动画资源
Glide.with(context)
  .load(url)
  .into(new SimpleTarget<>() {
    @Override
    public void onResourceReady(Drawable resource, Transition<GifDrawable> transition) {
      if (resource instanceof Animatable) {
        resource.start();
      }
      // Set the resource wherever you need to use it.
    }
  });

ViewTarget

Glide 并不支持加载图片到自定义 view 中,所以可以使用ViewTarget 来实现。

     CustomView customView = (CustomView) findViewById( R.id.custom_view );

    viewTarget = new ViewTarget<CustomView, GlideDrawable>( customView ) {
        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            //view.setImag是自定义view里自己去实现的方法
            this.view.setImage( resource.getCurrent() );
        }
    };

    Glide
        .with( context) 
        .load( url )
        .into( viewTarget );

Target下载图片文件

val future: FutureTarget<File> = Glide.with(context)
                .load(url)
                .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
val cacheFile: File = future.get()

清理

当你完成了对资源的使用时,需要及时清理创建的这些 Target 。即使请求已经完成了,也应该使用 clear() 以使 Glide 可以重用被这次加载使用的资源 (特别是 Bitmap )。未调用 clear() 会浪费 CPU 和内存,阻塞更重要的加载,甚至如果你在同一个 surface (View, Notification, RPC 等) 上有两个 Target,可能会引发图片显示错误。对于像 SimpleTarget这种无法从一个新实例里跟踪前一个请求的 Target 来说,及时清理尤为重要。


缓存

默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存:

1.活动资源 (Active Resources) - 现在是否有另一个 View 正在展示这张图片
2.内存缓存 (Memory cache) - 该图片是否最近被加载过并仍存在于内存中
3.资源类型(Resource) - 该图片是否之前曾被解码、转换并写入过磁盘缓存
4.数据来源 (Data) - 构建这个图片的资源是否之前曾被写入过文件缓存

前两步检查图片是否在内存中,如果是则直接返回图片。
后两步则检查图片是否在磁盘上,以便快速但异步地返回图片。

如果四个步骤都未能找到图片,则Glide会返回到原始资源以取回数据(原始文件,Uri, Url等)。

磁盘缓存策略

DiskCacheStrategy 可被 diskCacheStrategy 方法应用到每一个单独的请求。

DiskCacheStrategy.NONE -------------什么都不缓存
DiskCacheStrategy.DATA ------------- 仅仅只缓存原来的全分辨率的图像。
DiskCacheStrategy.RESOURCE -----仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
DiskCacheStrategy.ALL ----------------缓存所有版本的图像
DiskCacheStrategy.AUTOMATIC ----让Glide根据图片资源智能地选择使用哪一种缓存策略(默认选项

跳过磁盘缓存

Glide.with(context)
  .load(url)
  .diskCacheStrategy(DiskCacheStrategy.NONE)
  .into(view);

跳过内存缓存

Glide.with(context)
  .load(url)
  .skipMemoryCache(true)
  .into(view);

仅从缓存加载图片

省流模式下可以使用此方法

Glide.with(context)
  .load(url)
  .onlyRetrieveFromCache(true)
  .into(imageView);

清理缓存

Glide.get(context).clearDiskCache();//只能在子线程执行
Glide.get(context).clearMemory();//只能在主线程执行

调试

打开日志

Glide 的 GeneralRequest 类提供了一个方法去设置 log 的级别。需要用shell命令打开。

adb shell setprop log.tag.GenericRequest DEBUG  

RequestListener

Glide.with(fragment)
   .load(url)
   .listener(new RequestListener() {
       @Override
       boolean onLoadFailed(@Nullable GlideException e, Object model,
           Target<R> target, boolean isFirstResource) {
           
         Log.e(TAG, "Load failed", e);

         return false; // Allow calling onLoadFailed on the Target.
       }

       @Override
       boolean onResourceReady(R resource, Object model, Target<R> target,
           DataSource dataSource, boolean isFirstResource) {
           
         return false; // Allow calling onResourceReady on the Target.
         
       }
    })
//    .error(R.drawable.error)
    .into(imageView);

Module

Glide module 是一个抽象方法,全局改变 Glide 行为的一个方式。
自定义Module可以实现定制缓存大小、图片池大小以及改变解码规则等等功能,属于Glide的高阶使用技巧,本文不作展开。

参考资料
Glide官方文档:https://muyangmin.github.io/glide-docs-cn/
Glide系列博客:https://mrfu.me/2016/02/27/Glide_Getting_Started/ 作者:Yuan Fu

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值