图片加载工具Glide用法速览

来源:互联网 发布:化工工艺流程图软件 编辑:程序博客网 时间:2024/06/05 18:58

1. 前言

相对于Pissca,Glide是一款非常优秀的图片加载工具,由Google I/O 2015官方推荐。尤其是在内存上,那是相当的节省。推荐一篇关于Pissca和Glide在加载图片时的内存对比实验文章:Introduction to Glide, Image Loader Library for Android, recommended by Google,中文翻译版。Glide功能很强大,这里简要介绍一下。

2. Glide的相关原料

源码地址:Glide源码地址
一个相对不错的Glide文档:Glide — Advanced Loading
另外,使用过程中遇到什么异常可以在Glide的issues下寻找答案,作者还是很负责的。

3. 具体使用

3.1 一般用法

流畅的接口编程风格,用起来非常方便。

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);String internetUrl = "http://i.imgur.com/DvpvklR.png";Glide    .with(context)    .load(internetUrl)    .into(targetImageView);

注:加载的位置可以是Url,File,Uri,ResourceId

3.2 占位图和渐变动画(Placeholders & Fade Animations)

占位图片的使用:

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .placeholder(R.mipmap.ic_launcher) // can also be a drawable    .into(imageViewPlaceholder);

注:占位图来源不可以是网络请求
如果网络加载错误,还可以显示错误图片:

Glide    .with(context)    .load("http://futurestud.io/non_existing_image.png")    .placeholder(R.mipmap.ic_launcher) // can also be a drawable    .error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded    .into(imageViewError);

在占位图和加载图之间实现渐变:

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .placeholder(R.mipmap.ic_launcher) // can also be a drawable    .error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded    .crossFade()    .into(imageViewFade);

注:还可以使用它的重载函数.crossFade(int duration)来设定渐变时间
你也可以拒绝渐变(但是不推荐使用,失去了顺滑的效果,影响用户体验):

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .placeholder(R.mipmap.ic_launcher) // can also be a drawable    .error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded    .dontAnimate()    .into(imageViewFade);

3.3 重新设定图片大小和缩放

3.3.1 重新设定大小

默认情况下Glide一句ImageView的大小进行图片的加载,非常的节约内存与缓存。但同样你也可以手动的设定图片的大小。

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .override(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio    .into(imageViewResize);

这个中类型用在没有指定大小的targetView比较合适

3.3.2 图片的缩放

可以依据targetView对缩放后的图片进行处理
centerCrop():适配targetView的每个边之后,再进行裁剪

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .override(600, 200) // resizes the image to these dimensions (in pixel)    .centerCrop() // this cropping technique scales the image so that it fills the requested bounds and then crops the extra.    .into(imageViewResizeCenterCrop);

fitCenter():适配中心后裁剪

Glide    .with(context)    .load(UsageExampleListViewAdapter.eatFoodyImages[0])    .override(600, 200) // resizes the image to these dimensions (in pixel)    .centerCrop() // this cropping technique scales the image so that it fills the requested bounds and then crops the extra.    .into(imageViewResizeCenterCrop);

3.4显示gif动画和视频(Displaying Gifs & Videos)

方法同加载普通图片,但是有一个潜在的问题是,如果链接的地址不是一个gif,而你希望显示gif,这时如果加载出来的是图片也不会执行error,怎么办?你可以指定你的链接必须是gif资源,如果不是就显示错误图片信息:方法就是执行gif检查

Glide      .with( context )    .load( gifUrl )    .asGif()    .error( R.drawable.full_cake )    .into( imageViewGif );

相反的,如果你期待的是一个图片而不是一个gif你也可以执行检查:

Glide      .with( context )    .load( gifUrl )    .asBitmap()    .into( imageViewGifAsBitmap );

另外播放视频资源,只能来自本地资源。方法还是load()。不再赘述。

3.5 关于缓存

3.5.1 memory cache(内存缓存)

Glide      .with( context )    .load( eatFoodyImages[0] )    .skipMemoryCache( true )    .into( imageViewInternet );

3.5.2 本地缓存

Glide      .with( context )    .load( eatFoodyImages[0] )    .diskCacheStrategy( DiskCacheStrategy.NONE )    .into( imageViewInternet );

本地缓存策略:

  • DiskCacheStrategy.NONE 不缓存
  • DiskCacheStrategy.SOURCE 缓存原图
  • DiskCacheStrategy.RESULT 缓存结果图
  • DiskCacheStrategy.ALL 缓存所有(这个是默认的),由此来看还是不要这样设定,不然太占用空间了。

3.5.3 使单个缓存失效

这个貌似比较复杂,来看看关于这个问题的官方wiki
使本地缓存失效,是一个复杂的问题,有了缩略图后更甚之。
首先来介绍以下Cache Key的概念:
DiskCacheStrategy.RESULT策略的cache key包含以下四方面的信息:

  • getId() 返回的字符串,可以是文件路径,网址,等
  • 图片的宽高
  • 解码器和编码器使用的是getId返回的值作为依据来读取数据与缓存
  • 可以额外添加自定义的签名

In practice, the best way to invalidate a cache file is to change your identifier when the content changes (url, uri, file path etc).在实际应用中,使得缓存文件失效的最好方式是当内容改变时,改变识别id。
Custom cache invalidation自定义缓存失效:

由于改变id通常是困难或者说不可能的,glide提供了signature()的api用于混合增加你控制cachekey的部分。对于Media Store内容签名效果非常好,MediaStore的内容,你可以使用Glide的MediaStoreSignature类作为你自己的签名工具。MediaStoreSignature允许你混合文件改变日期,mime类型作为cache key。这三个属性比较可靠,你可以用它来缓存缩略图。

Passing in string signatures to loads is simple:传递一个字符串签名作为例子:

Glide.with(yourFragment)    .load(yourFileDataModel)    .signature(new StringSignature(yourVersionMetadata))    .into(yourImageView);

You can also define your own signature by implementing the Key interface. Be sure to implement equals(), hashCode() and the updateDiskCacheKey() method:
你也可以自定义你自己的签名通过实现Key接口,并确保实现其中的equals(),hashCode(),和updateDiskCacheKey()方法。
举个例子:

public class IntegerVersionSignature implements Key {    private int currentVersion;    public IntegerVersionSignature(int currentVersion) {         this.currentVersion = currentVersion;    }    @Override    public boolean equals(Object o) {        if (o instanceof IntegerVersionSignature) {            IntegerVersionSignature other = (IntegerVersionSignature) o;            return currentVersion = other.currentVersion;        }        return false;    }    @Override    public int hashCode() {        return currentVersion;    }    @Override    public void updateDiskCacheKey(MessageDigest md) {        messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());    }}

3.6 请求优先级

有时会同时遇到加载若干大图和若干小图的情况,因此为了提高用户体验,适当的设定大图小图显示的优先级,显得尤为重要:

  • Priority.LOW
  • Priority.NORMAL
  • Priority.HIGH
  • Priority.IMMEDIATE
    举个例子:
Glide        .with( context )        .load( UsageExampleListViewAdapter.eatFoodyImages[0] )        .priority( Priority.HIGH )        .into( imageViewHero );

3.7 缩略图Thumbnails

简单的说一下缩略图的优先级,缩略图配合优先级的使用可以有效提高用户体验。
简单略缩图的使用:

Glide      .with( context )    .load( UsageExampleGifAndVideos.gifUrl )    .thumbnail( 0.1f )    .into( imageView2 );

较为高级的用法:

DrawableRequestBuilder<String> thumbnailRequest = Glide        .with( context )        .load( eatFoodyImages[2] );    // pass the request as a a parameter to the thumbnail request    Glide        .with( context )        .load( UsageExampleGifAndVideos.gifUrl )        .thumbnail( thumbnailRequest )        .into( imageView3 );

3.8 Callbacks: SimpleTarget and ViewTarget for Custom View Classes 回调:SimpleTarget和自定义View类型的ViewTarget

之所以中SimpleTarget是因为又是我们加载而来的图片事没有目标ImageView的,

private SimpleTarget target = new SimpleTarget<Bitmap>() {      @Override    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {       //在这里你可以使用bitmap    }};private void loadImageSimpleTarget() {      Glide        .with( context ) // could be an issue!        .load( eatFoodyImages[0] )        .asBitmap()        .into( target );//设定target}

注:出于技术上的考虑,最好不要使用匿名对象作为target,因为可能会造成这样一种情况:glide还没有完成,而target就被回收了。因此最好是声明为字段

3.8.2指定大小的target

private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {      @Override    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {    }};

3.9 关于本地log和异常这里不详解了

3.10 自定义Transformations(图片转换规则)

先推荐一个Transformations仓库(https://github.com/wasabeef/glide-transformations),大家可以直接拿来用
如果是关于bitmap的自定义转换,建议继承BitmapTransformation 。
关于transformations的应用方式,可以单用,也可以混用:
单用的例子:

Glide      .with( context )    .load( eatFoodyImages[0] )    .transform( new BlurTransformation( context ) )    //.bitmapTransform( new BlurTransformation( context ) ) // this would work too!    .into( imageView1 );

混用的例子:

Glide      .with( context )    .load( eatFoodyImages[1] )    .transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )    .into( imageView2 );

3.11 自定义动画效果

除了上面介绍的crossFade(),我们也可以自定义自己的动画填充进去animate(Animation animation)
通过xml写的动画的使用:

Glide      .with( context )    .load( eatFoodyImages[0] )    .animate( android.R.anim.slide_in_left ) // or R.anim.zoom_in    .into( imageView1 );

通过自定义类定义的动画:

ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() {      @Override    public void animate(View view) {        // if it's a custom view class, cast it here        // then find subviews and do the animations        // here, we just use the entire view for the fade animation        view.setAlpha( 0f );        ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );        fadeAnim.setDuration( 2500 );        fadeAnim.start();    }};

应用:

Glide      .with( context )    .load( eatFoodyImages[1] )    .animate( animationObject )    .into( imageView2 );

—————————————————————————————–

未完待续

1 0