Glide & Picasso

因为Glide和Picasso的api差不多,所以比较起来更容易一点,就先比较这两个好了。

依赖

Glide

dependencies {
  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:19.1.0'
}

Picasso

dependencies {
  compile 'com.squareup.picasso:picasso:2.5.2'
}

别忘了Glide需要依赖Support Library v4。其实Support Library v4已经是应用程序的标配了,这不是什么问题。

使用

Glide

Glide.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

Picasso

Picasso.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

尽管它们看起来差不多,但是设计上Glide做得更好:因为Glide的with方法不光接受Context,还接受Activity 和 Fragment,Context会自动的从他们获取。

将Activity/Fragment传给Glide的好处是:图片加载会和Activity/Fragment的生命周期保持一致,比如Paused状态在暂停加载,在Resumed的时候又自动重新加载。所以我建议传参的时候传递Activity 和 Fragment给Glide,而不是Context。

默认加载格式 & 内存消耗

下面是将1920x1080的图片加载进入768x432大小的ImageView的对比图

glide和fresco的区别 glide fresco比较_加载


Glide默认的Bitmap格式是RGB_565,比ARGB_8888的内存开销要少50%。 下图是Picasso和Glide的内存消耗比较图(基础的application就消耗了大概8MB)

glide和fresco的区别 glide fresco比较_glide和fresco的区别_02

当然Glide也是可以指定加载格式的:

public class GlideConfiguration implements GlideModule {

    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        // Apply options to the builder here.
        builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
    }

    @Override
    public void registerComponents(Context context, Glide glide) {
        // register ModelLoaders here.
    }
}

同时在AndroidManifest.xml中将GlideModule定义为meta-data

<meta-data android:name="com.name.GlideConfiguration"
            android:value="GlideModule"/>

在指定了Glide的加载格式之后,我们再来看看内存消耗的对比图

glide和fresco的区别 glide fresco比较_加载_03


可以看到,Picasso占用的内存依然比Glide大。这是因为Picasso加载的是完整的图像(1920x1080)进入内存的。

而Glide是加载的真实ImageView(768x432)的大小进入内存的。

当然Picasso是可以调整加载图像的大小:

Picasso.with(this)
    .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
    .resize(768, 432)
    .into(ivImgPicasso);

当然,有时候你还无法明确的知道ImageView的大小,所以你还可以这么做:

Picasso.with(this)
    .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
    .fit()
    .centerCrop()
    .into(ivImgPicasso);

glide和fresco的区别 glide fresco比较_ide_04

缓存

Picasso和Glide在磁盘缓存策略上有很大的不同;Picasso缓存的是全尺寸的,而Glide缓存的是跟ImageView尺寸相同的。Glide的这种方式优点是在同样大小的ImageView下加载显示非常快。而Picasso的方式则因为需要在显示之前重新调整大小而导致一些延迟。

Picasso只缓存一个全尺寸的。Glide则不同,它会为每种大小的ImageView缓存 一次。尽管一张图片已经缓存了一次,但是假如你要在另外一个地方再次以不同尺寸显示,需要重新下载,调整成新尺寸的大小,然后将这个尺寸的也缓存起来。
当然我们也可以让Glide缓存完整的尺寸:

Glide.with(this)
     .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
     .diskCacheStrategy(DiskCacheStrategy.ALL)
     .into(ivImgGlide);

下次在任何ImageView中加载图片的时候,全尺寸的图片将从缓存中取出,重新调整大小,然后缓存。

Glide比Picasso多的功能

Glide可以加载GIF动态图,而Picasso不能。

还有一个特性是你可以配置图片显示的动画,而Picasso只有一种动画:fading in。

包大小

Picasso (v2.5.1)的大小约118kb,而Glide (v3.5.2)的大小约430kb。
Picasso和Glide的方法个数分别是840和2678个。

Fresco

关于Fresco

Fresco 中设计有一个叫做 Image Pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级磁盘)。

Fresco 中设计有一个叫做 Drawees 模块,它会在图片加载完成前显示占位图,加载成功后自动替换为目标图片。当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。

特性

内存管理

解压后的图片,即Android中的Bitmap,占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下,GC将会显著地引发界面卡顿。在5.0以下系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。Fresco 在低端机器上表现一样出色,你再也不用因图片内存占用而思前想后。

图片加载

Fresco的Image Pipeline允许你用很多种方式来自定义图片加载过程,比如:
- 为同一个图片指定不同的远程路径,或者使用已经存在本地缓存中的图片
- 先显示一个低清晰度的图片,等高清图下载完之后再显示高清图
- 加载完成回调通知
- 对于本地图,如有EXIF缩略图,在大图加载完成之前,可先显示缩略图
- 缩放或者旋转图片
- 对已下载的图片再次处理
- 支持WebP解码,即使在早先对WebP支持不完善的Android系统上也能正常使用!

图片绘制

Fresco 的 Drawees 设计,带来一些有用的特性:
- 自定义居中焦点
- 圆角图,当然圆圈也行
- 下载失败之后,点击重现下载
- 自定义占位图,自定义overlay, 或者进度条
- 指定用户按压时的overlay

渐进式呈现

渐进式的JPEG图片格式已经流行数年了,渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,这对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验。

动图加载

加载Gif图和WebP动图在任何一个Android开发者眼里看来都是一件非常头疼的事情。每一帧都是一张很大的Bitmap,每一个动画都有很多帧。Fresco让你没有这些烦恼,它处理好每一帧并管理好你的内存。

比较

以上说的都是一些Fresco的特性或者说强大的地方吧。但是它也有一些不是那么完美的地方:

包大小

Fresco > Glide > Picasso

操作

使用 DraweeView 时,请不要使用任何 ImageView 的属性: 在后续的版本中,DraweeView 会直接从 View 派生。任何属于 ImageView 但是不属于 View 的方法都会被移除。

Drawee永远会在getIntrinsicHeight/getIntrinsicWidth中返回-1。所以不能在xml中直接设置宽高为wrap_content

Fresco获取Bitmap的操作比较麻烦