1.前言Glide现在广泛应用于各种商业项目中,而且总的来说,Glide的Api封装非常好,大多数情况下我们只需要使用它,在此基础上使用,考虑如何理解它。这篇文章的目的是让你快速上手Glide3.x,让你快速投入开发。本文力求快速上手,所以只讲入门时需要注意的事项。这篇文章一开始只是想做一个简短的快速入门教程,但是在写的过程中,越来越长了。但是内容是我认为必须要解释清楚的,所以如果你想快速上手Glide,请耐心阅读。2.简单使用2.1什么是Glide?既然要用Glide,那我们先简单介绍一下Glide。Glide简单来说就是一个谷歌主导的图片加载开源库。稳定、快速、自适应图片大小、支持多种格式、支持加载不同来源的图片、优化内存和磁盘缓存。这些都是它的好处(当然不止这些),这里就不赘述了。你只需要知道它是一个主流的图片加载库,你能想到的功能都有,并且支持扩展。Glide的Github地址:https://github.com/bumptech/glide2.2在项目中集成Glide虽然已经到了v4.x,但是本文还是着重介绍最常用的v3.8.0版本的集成,做一个简单的介绍。集成的方式有很多种,可以直接引用jar包,也可以使用Maven,这里我们还是使用主流的Gradle来集成。如果需要配置混淆,还需要在混淆文件中区分Glide。Glide只是一个图片加载库,大多数情况下,我们的图片都来自于网络。所以它的网络请求库其实是可配置的,Glide可以支持OkHttp和Volley。这里使用另一个优秀的网络请求库OkHttp来支持。准备好Glide后,我们就可以开始使用它了。2.3Glide最简单的使用方法是支持链式调用,但是在每个方法中返回this并不简单,比较复杂,后面会讲到,所以通常只需要一条语句就可以使用。这是一个最简单的GlideDemo,可以用来从网络中加载一张图片到一个ImageView中进行显示。3.Glide需要知道什么前面的例子可以看。事实上,Glide的链式调用主要有三个方法。让我们先简单地看一下它们。与生命周期有关。load:接收一个需要加载的图片资源,可以支持多种格式。进入;指定加载图片的最终目标对象,例如可以是ImageView。这三个主要部分贯穿了Glide使用的主要重点。让我们仔细看看它们。3.1with()前面说过,这里的with()方法是用来传递一个Context对象给Glide的,Glide可以支持多个Context。对于with,它会返回一个RequestManager来管理请求,它接收到的不同的Context并不是为了方便我们,而是会监听当前Context的生命周期来管理Glide自己的图片加载请求。例如:在使用with(Activity)时,如果此时当前Activity是关闭的,那么Glide会停止这个Activity下的所有图片请求。也就是说,实现Glide和页面声明周期的绑定,优化Glide自身的请求策略。因此,在使用Glide时,尽量使用当前页面的Activity,而不是直接传递一个Context。选择尽可能小的Context范围。他们推荐的优先顺序是:Fragment>Activity>Context3.2load()load()方法是指定一个要加载的资源,它支持很多格式和资源类型。比如:网络地址、本地文件、Drawable等,都可以很好的加载。Glide中没有load()方法。前面说过,with()会返回一个RequestManager对象,里面实现了load()方法。具体的load()方法,支持的资源类型,可以看其方法的重载。基本上,它支持我们能想到的一切。有趣的是load()方法,它返回另一个DrawableTypeRequest对象。3.3into()into()方法用于指定最后谁来使用加载的图片资源。对此无话可说。加载的图片最终要用于显示,所以需要指定一个使用该图片的对象。into()其实是DrawableTypeRequest中的一个方法。DrawableTypeRequest是一个多层继承类。它实际上并没有实现into()方法本身。大部分的实现都在它的父类DrawableRequestBuilder和父类的父类中。类GenericRequestBuilder,但这并不影响我们对它的使用。从方法的签名可以看出,into()不仅可以接受ImageView,还可以接受其他东西。这也很好理解。在项目中,不仅可以使用ImageView来显示图片,还可以使用View的背景来显示图片。除了前面介绍过ImageView,大家可以直接使用。其余的将在以后讨论。4、使用Glide的细节现在已经介绍了Glide使用过程中最重要的三个方法,它们是Glide完成功能的基础。接下来,我们将介绍使用Glide的细节,见证Glide的强大。本节介绍的Glide的使用细节,基本上都是对load()方法返回的DrawableTypeRequest对象进行操作,并对其进行配置。4.1不同状态的Occupier图片在图片加载过程中会经历过多的过程,比如:加载,加载失败等,在这些过程中,其实可以临时给ImageView设置一个placeholder来自定义图片的显示效果加载和加载失败的状态。Glide自定义的占位图片一共有三种:placeholder:指定加载前显示的图片资源。error:指定加载失败的图片资源。fallback:指定当传入的loading资源为null时显示的图片资源。比如上面的例子,其实fallback()是不需要指定的,因为imageUri不能为null。其他的会在不同阶段显示,加载前会显示load_placeholder,加载失败会显示load_error。注意不同状态下的占用图其实是一种容错性能,所以只能用来加载一个“本地资源”,允许传入一个@DrawableId或者Drawable对象。4.2缩放控件有时候,因为图片的大小和控件的大小可能不匹配,所以会对图片的显示效果进行一些缩放,而大多数情况下,这种默认的缩放策略并不是我们想要的.Glide提供了一些方法来控制缩放效果。centerCrop()fitCenter()这两个方法和ImageView.setScaleType()中传入的参数类似,不再一一赘述。4.3缓存控制现在基本上所有的图片加载库都遵循三级缓存策略:网络、磁盘、内存。Glide也是如此,默认情况下,这些缓存都是开启的,以获得更好的体验。就Glide的缓存策略而言,我们其实是有办法调整的。对于内存缓存,只有yes或者no的情况,所以Glide只提供了一个skipMemoryCache()方法,可以传递一个布尔值来指定是否跳过diskcache。默认为false,表示需要内存缓存。但是对于磁盘缓存来说,就有点复杂了。为了保证效率,Glide实际上默认在磁盘上缓存了多种尺寸的图片。也就是说,对于同一个Uri,如果你在不同大小的ImageView中使用,默认情况下,在你设备的磁盘上,也会有多个不同大小的图片。这是为了下次加载更快,不需要处理原始图像。这是一种以空间换效率的策略。而如果我们需要调整磁盘缓存,就需要使用diskCacheStrategy()方法来改变。前面说了,这是一个比较复杂的策略,不能简单的用一个布尔值来完成。它需要传递一个DiskCacheStrategy枚举类型。可以看到,它其实是通过两个参数来标记磁盘缓存策略的。ALL:缓存所有类型的图像(默认行为)。NONE:禁用磁盘缓存。来源:仅缓存全尺寸原始图像。结果:仅缓存压缩图像。所以要用哪个,需要看当前加载的图片是属于哪个的。上面的例子是忽略内存缓存,只缓存磁盘上的原始图像的策略。4.4加载优先级对于同一个页面,如果需要在多个地方加载在线图片,必然会出现优先级的问题。例如:通常情况下,背景图像是比其他图像具有更高优先级的图像。Glide可以在加载时调整当前加载图片的加载优先级。需要用到priority()方法,它可以接受一个Priority枚举类型,包括四个值:LOW(低)、HIGH(高)、NORMAL(正常)、IMMEDIATE(立即)。它可以在我们需要的时候配置,但不影响Glide加载图片的显示顺序,它只是Glide加载图片时的一个优化请求的参数,不影响最终的显示顺序。4.5加载动画在显示图片的时候,为了让显示效果不那么突兀,Glide会以比较柔和的方式显示,并且在加载的时候会给出一个动画效果,可以使用crossFade()方法来配置,如果没有特别的处理,默认开启,默认动画时长300ms。crossFade()也有多个重载,主要是指定动画和动画持续时间。有兴趣的也可以看看crossFade()的源码,其实只是对animate()方法的一个包装,后面会讲到。crossFade()效果是默认开启的,所以如果我们不需要这样的动画效果,可以使用dontAnimate()来关闭动画效果。在某些情况下,crossFade()方法并不能满足我们的需求。如果你对加载的动画有特殊的定制需求,可以使用更灵活的animate()方法自己实现动画。可以看出animate()支持多种格式动画的配置,动画的效果这里就不一一说明了。4.6支持Gif&VideoGlide的一大特点就是可以支持Gif,使用起来和从网上加载图片没有区别。在上面的例子中,Gif图片的效果会显示在mBgImageView中并自动播放,加载前可以为其设置一个占位符图片,与加载普通图片没有区别。但有时我们需要检查加载的Gif图片,比如检查是否是Gif,如果不是,则认为加载错误。这时候可以使用asGif()进行校验。如果当前加载的图片不是正确的Gif格式,将显示error()配置的图片。当然,有时候我们可能只是显示一张图片,我们可以强制显示Gif图片的第一帧,使用asBitmap()方法来标记。你只需要用asBitmap()替换asGif(),你就会饿了。此处不提供单独的示例。除了Glide对Gif的支持外,提示还支持Video格式的文件。但它与Gif显示的区别在于它不播放视频文件,只是将视频文件的第一帧显示为图片。如果你仍然想播放一个视频文件,那么使用Glide并不是一个好主意,你应该使用VideoView。其次,Glide对视频的支持仅限于本地视频,无法支持网络视频。4.7加载监听如果想监听Glide加载图片的结果,可以使用listener()方法设置一个监听器,监听器接收一个RequestListener接口。一般来说,如果我们需要监控图片加载错误的原因,可以使用onException()进行处理。需要注意的是,这两个方法的返回值始终为false,因为如果返回true,就说明你已经处理了这个事件,Glide不会做额外的处理。例如,如果onException()返回true,图片加载失败后,error()中设置的图片将不会显示,因为Glide认为开发者已经在外部处理了错误。4.8对加载的图片进行变换对于使用Glide加载的图片,如果想在显示之前对其进行一些变换操作,例如改变颜色、模糊、圆角子类,则需要使用transfrom()方法。主要用于支持图片显示前自定义变换效果。Transform有两个方法:transform():可以添加一个通用的变换效果。bitmapTransfrom():限制变换的类型,只能设置Bitmap的变换。改变这种操作,其实是非常可定制的,扩展起来比较复杂。你只需要知道,Glide可以在显示之前对加载的图片进行一些预处理操作,真正使用的时候再回来处理。看看相关资料就知道了。这里推荐一个开源库来支持大部分的变换效果。Github地址:https://github.com/wasabeef/glide-transformations4.9into()其他实现在前面所有的例子中,into()方法都是Glide图片加载过程中的最后一个环节。支持ImageView。有时候我们还需要给View设置一个背景。这也可以用Glide来完成,但是我们需要使用into()方法的其他重载方法。抛开into(ImageView)不谈,into(int,int)其实就是一个指定大小的同步方法,可以用来在子线程中获取一个GlideDrawable对象。但这不是一个很常见的场景,我们大多数人仍然以通用的方式使用Glide。从它的完整签名可以看出,它实际上接收的是一个Target对象,Glide也提供了很多Target的子类。其中一些子类并不常用。比如AppWidgetTarget和NotificationTarget就是为AppWidget和Notification加载图片准备的。这里只介绍两个常用的Target:SimpleTarget和ViewTarget,但是它们的用法都差不多。如果我们不关心图片加载的目的,而只是简单的需要加载一个Bitmap或者Drawable,我们可以使用SimpleTarget来处理。SimpleTarget可以接受GlideDrawable或Bitmap类型作为加载类型。如果需要指定加载图片的大小,也可以在构造方法中指定。如果不指定,则加载图片的原始尺寸。让我们再看看ViewTarget。只能从名字上看出来。它其实是想让Glide加载一个图片资源给某个View使用。可以解决有时候我们展示图片的View不是ImageView,也有可能是View的背景的问题。ViewTarget需要指定View的类型和加载的资源类型。这里直接使用View和GlideDrawable,然后将我们需要使用图片的目标View作为构造参数传入即可。最后,它会是一个内部视图变量来保存它,以备后用。在回调方法onResourceReady()中,根据我们的需要直接使用GlideDrawable和View即可。如果需要在ImageView以外的其他View上使用图片,推荐使用ViewTarget。在内部,它计算视图的大小以优化缓存的图像。效果和加载ImageView是一样的,如果使用SimpleTarget,需要考虑View的大小。在使用Target的时候,还有一点需要注意。前面说过,这次Glide加载图片的生命周期会绑定with()传入的Context的生命周期,所以在使用Target加载图片的时候需要格外注意,如果是未绑定页面Image资源,可以使用ApplicationContext()来防止当前页面销毁后停止加载请求。5.总结这篇文章开始的时候只是想做一个适合初学者快速上手的Glide使用手册,但是越写越长。相信看完这篇你一定会有所收获。如果觉得自己有写作的概念,需要初学者才能看懂。会继续补充的。【本文为专栏作家“张扬”原创稿件,转载请微信♂联系作者获得授权】点此查看作者更多好文
