Glide教程5-8

5. Glide-图片缩放、调整 (Resizing & Scaling)


在上一篇博文里,你学习了如何从不同的源加载图片并且设置不同的占位符。如果你还不会在加载的时候调整和裁剪图片,那么本周的博文就很重要啦!

用resize(x,y)设置图片大小

通常来说,如果你的服务器或者API能为你提供你需要的尺寸的图片,那么是最好的。因为这需要在带宽、内存消耗、图片质量之前做一个平衡。
与Picasso相比,Glide在内存消耗上更高效、更智能。Glide会根据所剩的内存和ImageView的大小自动限制图片的尺寸。Picasso也有相似的特性,但是它需要手动调用.fit(),对于Glide而言,如果某些图片不应该被自动调整,那么执行override(horizontalSize, verticalSize),那么这个图片会在显示到ImageView之前被调整为需要的尺寸。

Glide  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .override(600, 200) //按照这个像素,调整图片的尺寸,不保持长宽比例
    .into(imageViewResize);

这对于某些情况是挺实用的:当你要加载图片到未知尺寸的View上时;比如,如果app想要在启动页面加载缓存(原文:if the app wants to warm up the cache in the splash screen( warm up the cache不知道啥意思(逃),此时还不能测量ImageView的尺寸。然而,如果你已经知道图片需要多大的尺寸,那么使用override可以得到特定大小的图片。

图片裁剪

现在,因为任何对图片的处理、调整都会导致图片的比例扭曲从而图片看起来很丑。在大部分应用场景下,你都希望避免这种情况的发生。Glide提供了一些常用的变换来改变图片的显示。它附带了两个基本选项: centerCrop和fitCenter。

CenterCrop

CenterCrop() 是一种“去除多余”的裁剪方式,它会把ImageView边界以外的部分裁剪掉。这样一来ImageView会被填充满,但是这张图片可能不会完整地显示出来(ps:因为超出部分都被裁剪掉了)。

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

FitCenter() 是一种“中心匹配”的方式裁剪方式,它裁剪出来的图片长宽都会小于等于ImageView的大小,这样一来。图片会完整地显示出来,但是ImageView可能并没有被填充满。

Glide  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .override(600, 200)
    .fitCenter() 
    .into(imageViewResizeFitCenter);

在后面的文章里,我们将会提到除了CenterCrop和FitCenter以外,其他一些自定义的变换。

展望

在这篇文章里,学习了如何调整图片显示的尺寸。这对于设计一款优秀的app是非常有用的。在我们学习Glide更多高级应用之前,我们再多讲一个Glide特有的功能:显示Gif图片和视频。



6. Glide-显示Gif和视频

在前面的文章我们讲了如何从各种数据源加载并显示图片,我们学习了如何改变图片:通过一些标准的方法设置图片大小、裁剪。
本文将讲述Glide特色功能:显示Gif图片和本地视频。

显示Gifs

有很多图片加载框架提供了加载并显示图片的功能,但支持Gif则有点特殊,如果你的app需要这个功能,那么它非常必要。Glide加载Gif的体验让人惊叹,因为它非常简单。如果你想显示Gif,你只需要像之前那样写就可以了:

//这动图吓我一跳 - -#
String gifUrl = "http://i.kinja-img.com/gawker-media/image/upload/s--B7tUiM5l--/gf2r69yorbdesguga10i.gif";

Glide  
    .with( context )
    .load( gifUrl )
    .into( imageViewGif );

就是这么简单!这样就可以在ImageView上显示一个Gif图片了,并且它是自动播放的。更酷的是你依然可以像之前那样做一些额外的处理:

Glide  
    .with( context )
    .load( gifUrl )
    .placeholder( R.drawable.cupcake )//加载出来前显示的图片
    .error( R.drawable.full_cake )//加载失败后显示的图片
    .into( imageViewGif );

Gif Check :确保是Gif图片

以上代码潜在的问题是:如果你的图片源存放的不是一张Gif,那么可能只是一张普通的图片,没有办法声明这种情况。Glide允许Gifs或者是普通图片作为load()方法的参数,如果开发者认为URL是一张Gif,而实际上不是的话。Glide没有办法自动检测到。因此,这里提供了另一种方法,来确保Glide请求到的是一张Gif动图 asGif():

Glide  
    .with( context )
    .load( gifUrl )
    .asGif()
    .error( R.drawable.full_cake )//加载失败 的图片
    .into( imageViewGif );

如果gifUrl指向一张Gif图片,那么万事大吉。但如果不是,那么与之前不同的是,此时Glide会认为是加载失败。那么就有一个好处,.error()方法会被回调过来,那么就会显示我们指定的 加载失败 的图片。就算gifUrl指向一张完美的图片(啥图?),只要它不是Gif动图,还是会被认为是加载失败。

Cache Settings :缓存设置

在大多数情况下,如果你调用了.diskCacheStrategy(DiskCacheStrategy.SOURCE),那么加载Gif的时候明显会更快:

Glide  
    .with( context )
    .load( gifUrl )
    .asGif()
    .error( R.drawable.full_cake )
    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
    .into( imageViewGif );
作者:我们将在12月份出一个新的教程:讲述关于 Glide缓存 的更多的细节和背后实现;

Display Gif as Bitmap:将Gif转为Bitmap显示

如果你的app通过一个包含许多图片链接的列表(List<url>)来显示图片,那么可能会包含普通图片和Gif动图。有时候你可能想不要完整地播放整个Gif图片,如果你只想要显示Gif的第一帧画面,那么asBitmap()就可以保证作为一张普通的图片来显示,即使链接指向的是一张Gif动图。

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

以上,就是所有Glide显示Gifs图片的知识,非常简单,试试吧!

Display of Local Videos:播放本地视频

Gif的加强版就是视频啦,Glide同样可以显示视频文件的缩略图,并且是和视频同样长度的。假设我们通过让用户选择来获取一个视频文件的路径:

String filePath = "/storage/emulated/0/Pictures/example_video.mp4";

Glide  
    .with( context )
    .load( Uri.fromFile( new File( filePath ) ) )
    .into( imageViewGifAsBitmap );

再次提醒:这只对本地视频文件有效!其他不是存储在设备上的视频(比如网络视频)是不能播放的。另外,它只会显示视频的第一帧画面。
如果你想播放视频或者从网络链接上查看视频,那么试试这个 VideoView.(这个需要f墙,贴一篇简书的

Outlook:展望

读完这篇文章,你应该可以像加载普通图片一样去加载Gif和本地视频文件了。Glide使得显示Gif图片非常流畅、方便;下一周,我们将介绍Glide的缓存机制。



6. Glide-缓存基础(caching-basics)

在了解完图片的加载、显示、处理之后,接下来继续研究优化。成功、高效加载图片的基本特性之一就是利用缓存。在本文,我们将会了解Glide的缓存机制的基础部分。

Cache Basics:缓存基础

在设计一款Android应用的时候,一个好用的图片加载框架应该尝试最小化网路请求的次数。Glide也一样,Glide默认通过内存和磁盘缓存来避免不必要的网络请求。在后续的文章中我们会具体看看其实现细节。如果你已经迫不及待,随时可以查看这个官方文档
对于现在,重要的是,所有的图片请求都会在内存和磁盘上建立缓存。缓存通常都是非常有用的,然而在某些情况下又不希望它这么做。在下一节,我们将学习如何在一次请求中改变Glide的缓存策略。

Using Cache Strategies:使用缓存策略

如果你使用过Glide,你注意到根本不需要为开启缓存做额外的事,它自然而然就实现了。然而,如果你知道某张图片改变非常快,那么你应该要避免某些缓存。

Glide提供了一些方法来调整内存和磁盘缓存策略,让我们先来看看内存缓存。

Memory Cache:内存缓存

我们假设一种非常简单的情形:从网络上加载一张图片到ImageView上:

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

你已经注意到我们这里使用.skipMemoryCache( true )来特地告诉Glide,让它跳过内存缓存。这意味着Glide不会将它放入到内存缓存当中。需要注意的是,这只是影响了内存缓存,Glide依然会使用磁盘缓存来避免额外的网络请求。

很容易理解的是,Glide是默认将所有的图片资源都加入到内存缓存中的。因此,没有必要专门去调用.skipMemoryCache( false )这个方法。

提示:要注意的是,对于同一个图片链接,如果你初次请求的时候没有调用.skipMemoryCache( true ),后面又调用了这个方法,那么它会被加入到内存缓存当中。当你想调整缓存策略的时候,确保你在请求同一个图片的时候保持策略统一。

Skipping Disk Cache:不使用磁盘缓存

基于你已经学习完上面的章节,你知道即使让内存缓存失效,图片请求依然会将图片存储在设备的磁盘上。如果你有一张图片,它指向同一个链接上,但是它改变得很快,那么你可能也不想让它存储在磁盘上。

你可以通过.diskCacheStrategy()方法改变Glide的磁盘缓存策略。与.skipMemoryCache()不同的是,它需要传入不同的枚举值,而不仅仅是布尔值。如果你想让磁盘缓存失效,将DiskCacheStrategy.NONE作为参入传入即可:

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

这样的话,这张图片的一点磁盘缓存都不会有。然而,它默认会使用内存缓存。为了让两个缓存都失效,把它俩组合一下就好:

Glide  
    .with( context )
    .load( eatFoodyImages[0] )
    .diskCacheStrategy( DiskCacheStrategy.NONE )//它
    .skipMemoryCache( true )//还有它
    .into( imageViewInternet );

Customize Disk Cache Behavior:自定义磁盘缓存策略

我们前面已经提到了,对于磁盘缓存,Glide不止一个选项。在知道有哪些选项之前,你要明白磁盘缓存是相当复杂的东西。例如,Picasso只是缓存完整图片。然而,Glide的缓存不仅缓存原图、完整的图片还有额外一些缩小的图片。
例如,如果你请求一张图片是1000 x 1000像素,然后你的ImageView是500 x 500像素,那么Glide会将这两个尺寸图片都缓存起来。
现在你应该明白磁盘缓存策略diskCacheStrategy()中,不同的枚举参数之间的区别了:

  • DiskCacheStrategy.NONE 就像上面讨论的,啥都不缓存
  • DiskCacheStrategy.SOURCE 只缓存原图,在我们上面的例子中就是 1000 x 1000像素的那张
  • DiskCacheStrategy.RESULT 经过裁剪、调整后,只缓存最终的图片(这是默认选项
  • DiskCacheStrategy.ALL 缓存所有版本的图片

作为最后一个例子,如果你有一张图片,你知道会经常修改它并且会有各种不同的版本,那么把它指定为仅缓存原图是很有意义的。因此,我们可以使用DiskCacheStrategy.SOURCE来告诉Glide仅缓存原图即可:

Glide  
    .with( context )
    .load( eatFoodyImages[2] )
    .diskCacheStrategy( DiskCacheStrategy.SOURCE )
    .into( imageViewFile );

Invalidate Cache for Single Image:不缓存某张图片

由于Glide对于同一张图片可以采取不一样的的缓存方式,想要简单的清除某张图片的缓存不是一件容易的事。你需要找到这张图片所有的变体,然后针对性地让那个缓存失效。
这是一个相当繁琐的步骤,官方文档里讲解得非常清楚。

展望

在本文,你学习了Glide缓存图片的基础知识,并且知道如何调整缓存策略。基于你的需求,在后续的博文里,我们将回到这个话题讲解更多高级的优化。然而,这篇文章已经提供了非常有效的方法让你可以好好地利用Glide的缓存了。

下周,我们将看看 良好的用户体验的另一个关键点:优先图片请求!



7. Glide-图片请求优先级(request-priorities)

上一周,我们讲了图片加载的一个关键:缓存! 如果你还没有看过,那么值得翻回去看看。本周,我们将了解Glide的另一个重要特性:按照优先级依次请求图片。

Prioritizing Image Requests:设置图片请求优先级

你经常会遇到这样的情况,你的app需要同时加载许多图片。我们假设有这样一个详情页面:页面上方有一张关键的大图和两张稍小一些的图,页面底部还有一些不那么重要的图片。 对于一个良好用户体验来说,上方的关键大图应该是最先被加载并显示的,然后再到底部那么不那么重要的ImageView。Glide通过.priority()方法结合Priority的枚举值即可按照你想要的优先级来加载图片。

但是在我们讲例子如何使用这个方法之前,我们先来看看这些枚举值,它们是作为.priority()的参数传入的。

Getting to know the Priority enum:优先级的枚举值

这些枚举总共有四种,优先级按照顺序依次递增:

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

immediate
adj. 立即的; 立刻的;

在我们看例子之前,你要明白这些优先级并不是非常严格执行的。 Glide会将它们作为一个参考,在请求的时候尽量满足,并不保证所有的图片都会按照顺序来请求。

但是,如果你确定某些图片非常重要,那么可以好好利用这个特性!

例子: Hero Element with Child Images

我们回到刚才提到的例子:你要实现这么一个详情页面:顶部有关键的图片,底部有一些小图。最佳的用户体验应该是:顶部的图片最先加载出来。 因此,我们给它设置Priority.HIGH优先级。理论上,这么做已经足够了。但是为了让这例子更有趣,我们让底部的图片都以.priority(Priority.LOW)优先级加载:

private void loadImageWithHighPriority() {  
    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[0] )
        .priority( Priority.HIGH )
        .into( imageViewHero );
}

private void loadImagesWithLowPriority() {  
    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[1] )
        .priority( Priority.LOW )
        .into( imageViewLowPrioLeft );

    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[2] )
        .priority( Priority.LOW )
        .into( imageViewLowPrioRight );
}

如果你运行这个例子,你会发现几乎每次都是顶部的图先加载出来,尽管它比较大(那样它需要更长时间来加载)。

Outlook:展望

Glide提供了非常方便的方法来设置图片的优先级。这是一个快速、简单提高一些用户体验的的方法。看看你的app和你的代码,是否能运用到你刚学到的技巧吧!

按优先级请求通常来说非常有效,但不能解决所有的问题。假设你要下载一张非常大的图片,如论你设置了什么优先级,下载和处理都要花费一定的时间。
下一周,为了更好地提升用户体验,我们将介绍另一个Glide外的工具:thumbnails!



8. Glide-缩略图(thumbnails)

上周,我们学习了一些在加载和显示图片的时候提高用户体验的方法。通过 缓存设置请求优先级 已经为流畅的体验提供了关键的一步了。然而,如果你加载的图片非常大,那么会花费较长的一段时间直到它显示出来。在本博文中,我们将探索另一个优化的途径:thumbnails(缩略图,下文不译)

Thumbnails的优势

在你使用Thumbnails来优化之前,先确保你已经理解并充分利用了 缓存优先请求。如果所有的努力都已经做了,那么试试Thumbnails是否能提升你的Android应用。

Thumbnails跟我们之前讲的占位符还不太一样,占位符在app里面是指定好的某些资源文件。Thumbnails的话则是一个动态的占位符,它也可以从网络上加载得来。
Thumbnails会在实际的请求和处理之前显示出来,不管什么原因,如果Thumbnails在原图加载后才出现,它会自动消失而不会替换原图。

提示:为了更加时更加流畅,另一个非常好的方式是用一种颜色来替换占位符的背景色,这个颜色是从目标图里提取出来的,可以看看我们写的一个文档

ps:以下是我从作者提到的文档里面抠出来的图,来感受一下:

Simple Thumbnails:简单缩略图

Glide提供了两种不同的缩略图。第一种比较简单,就是在加载原图的时候显示一张更小尺寸的图片。这种方式尤其适用于ListView和详情页面的组合当中。 如果你早已经在ListView中加载了图片,就像我们刚才假设的,250x250像素的图片,在进入其详情页面的时候,需要一张更大尺寸的图。然而,对于用户而言。他们早早就已经看到一张图片(小图)了,为什么还会出现先显示占位符,过了几秒后显示大图的情况?

对于这种情况,我们更应该在详情页面继续显示那张250x250的图片,然后在后台加载所需要的大图。Glide使用.thumbnail()就可以做到,这是传入的参数是一个浮点数,它代表尺寸的倍数。

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

例如,你传了0.1f作为参数,那么Glide则会显示原图大小的10%。如果原图的尺寸是1000x1000像素,那么缩略图就是100x100像素。由于缩略图会比ImageView要小许多,所以你要确保一个准确的缩放比例。

说明一下,所有图片请求的设置同样适用于缩略图。例如,你请求某张图片时做了一个灰度变换,那么对于它的缩略图也是同样会生效的。

Advanced Thumbnails with Complete Different Requests 高级缩略图,通过完成不一样的请求

虽然使用.thumbnail()传入一个浮点数非常简单高效,但不是所有情况都使用。如果缩略图也需要从网络加载各种尺寸,那么它可能也快不了多少。因此,Glide提供了另一种加载缩略图的方法。

第二种方式就是传入一个新的图片请求作为参数,我们来看看例子:

private void loadImageThumbnailRequest() {  
    // setup Glide request without the into() method
    DrawableRequestBuilder<String> thumbnailRequest = Glide
        .with( context )
        .load( eatFoodyImages[2] );

    // pass the request as a parameter to the thumbnail request
    Glide
        .with( context )
        .load( UsageExampleGifAndVideos.gifUrl )
        .thumbnail( thumbnailRequest )
        .into( imageView3 );
}

区别在于第一个图片请求与第二个图片请求是完全独立的,缩略图可以是其他不同的资源id或者图片链接,你可以对它做一些变换等等。

提示:如果你想更带劲一点,你可以递归地调用一些请求作为图片的缩略图请求参数

Outlook: 展望

本文介绍了Glide两种加载缩略图的方式,不要忘记在你的优雅的app上使用哦!它能极大地减少空白的ImageView出现在你的app上。如果你有什么疑问,请通过评论让我们知道!

下周,我们将学习如何在不是ImageView的控件上显示图片,敬请关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值