目前来看Android市场上主流的图片库主要有:
Android-Universal-Image-Loader (Android-Universal-Image-Loader源码)
Picasso(Picasso源码)
Glide(Glide源码)
Fresco(Fresco源码)
其中Android-Universal-Image-Loader出来的最早,之前有很多APP都是用的Android-Universal-Image-Loader图片库,但是Android-Universal-Image-Loader近期已经不维护了,比较遗憾,不再推荐使用。所以我们这次讨论的范围并不包含Android-Universal-Image-Loader,只讨论剩下的三种库Picasso、Glide、Fresco。
由大名鼎鼎的Square公司的一个开源项目,Square出过很多精品,比如我们常用的Okhttp即出自Square之手。Picasso继承了Okhttp的链式调用风格,使得它使用起来非常简单和方便,并且它的设计和实现也很轻量简单,使得整个库的接口数量和体积都很小,因此被很多开发者使用在项目中。
是Google推荐的一个图片库,作者是Google的一位大牛bumptech。它在Picasso的基础上做了很多的改进和优化,使得图片在加载想能上比Picasso要好,并且保留了Picasso的许多优良特性,因此被广大开发者所推荐使用。
是Facebook开发的一个开源框架,功能也很强大。尤其是在图片缓存这块更是使用了黑科技来提高缓存效率。
三类图片库基本项对比如下(红色表示对比下的重要缺陷):
对比项 |
Picasso |
Glide |
Fresco |
---|---|---|---|
开发者 | Square主导 | Google主导 | Facebook主导 |
发布时间 |
2013年5月 |
2014年9月 |
2015年5月 |
是否支持gif |
false |
true |
true |
是否支持webP |
true |
true |
true |
视频缩略图 |
false |
true |
true |
大小 |
100k |
500 KB |
2~3M |
加载速度 |
中 |
高 |
高 |
Disk+Men Cache |
true |
true |
true |
Easy of use |
low |
mediun |
difficult |
star |
16677 |
25746 |
15556 |
加载图片耗时及内存对比(without animations):
对比项 |
Picasso |
Glide |
Fresco |
---|---|---|---|
max java heap |
12.6MB |
11.1MB |
13.9MB |
max native heap |
43.8MB |
43.8MB |
43.8MB |
avg wait time |
241ms |
34ms |
44ms |
从上面的加载静态图片可以看出三大主流框架性能都不错,不过用数据说话整体而言Glide更胜一筹。
加载图片耗时及内存对比(allow animations):
对比项 |
Picasso |
Glide |
Fresco |
---|---|---|---|
max java heap |
6.8MB |
74.8MB |
36.1MB |
max native heap |
18.2MB |
66.8MB |
545.3MB |
avg wait time |
1707ms |
33910ms |
15142ms |
上面的数据我们可以忽略Picasso了,因为它根本不支持gif,那么Glide和Fresco可以看出Fresco的java heap基本保持较低平稳状态,而Glide的java heap基本为Fresco的一倍,所以OOM的风险也比fresco大一倍。 从时间上glide是有一定差距,不过fresco有两张图片没加载完成,所以时间不是完全可靠的数据 从native heap可以看出Fresco最高545MB,这个有点恐怖。
再往下分析,由于Picasso不支持gif,且各方面性能也不是很好,所以暂时先将其排除了。下面只拉出Glide及Fresco进行对比。
对比项 |
Glide |
Fresco |
---|---|---|
初始化 |
直接使用 |
Fresco.initialize(this); |
layout |
普通ImageView |
独有的SimpleDraweeView |
圆角, 圆形 |
需要自己实现圆角,继承自BitmapTransformation操作bitmap对象实现 |
通过RoundingParams设置参数 |
缓存 |
Glide内存和磁盘缓存 |
三级缓存,分别是 Bitmap缓存,未解码图片缓存, 磁盘缓存。 |
缓存图像大小 |
Glide则会根据ImageView控件尺寸获得对应的大小的bitmap来展示,从而缓存也可以针对不同的对象:原始图像(source),结果图像(result) |
缓存原始图像 |
加载策略 |
Glide只有占位图 |
先加载小尺寸图片,再加载大尺寸的 |
加载进度 |
false |
true |
从上面的对比中可以看出来Fresco蛮强大的,不过使用起来相对Glide要复杂一点,而且需要自己的SimpleDraweeView,这一点在切换框架的时候最让人头疼了。而且Glide直接缓存相对大小的图片,节省空间的同时下场如果是同样大小的图片就不要再次请求,直接可以使用。
这里说到了Fresco特有的三级缓存(Bitmap缓存+未解码图片缓存+硬盘缓存),那么我们就简单介绍下:
前两个就是内存缓存,Bitmap缓存根据系统版本不同放在了不同内存区域中,而未解码图片的缓存只在堆内存中,Fresco分了两步做内存缓存,这样做有什么好处呢?第一个好处就如上的第二条,第二个好处是加快图片的加载速度,Fresco的加载图片的流程为:查找Bitmap缓存中是否存在,存在则直接返回Bitmap直接使用,不存在则查找未解码图片的缓存,如果存在则进行Decode成Bitmap然后直接使用并加入Bitmap缓存中,如果未解码图片缓存中查找不到,则进行硬盘缓存的检查,如有,则进行IO、转化、解码等一系列操作,最后成Bitmap供我们直接使用,并把未解码(Encode)的图片加入未解码图片缓存,把Bitmap加入Bitmap缓存中,如硬盘缓存中没有,则进行Network操作下载图片,然后加入到各个缓存中。
由上分析可知Glide的优点:
1、支持多种图片格式的缓存,例如Gif、WebP、缩略图、Video。
2、支持根据Activity及Fragment的生命周期的变化来处理图片。
3、高效的缓存策略,灵活(Picasso只会缓存原始尺寸的图片,Glide缓存的是多种规格)。
4、加载速度快且内存开销小(默认Bitmap格式的不同,使得内存开销是Picasso的一半)
5、包大小只有500k左右,比Fresco小不少。
Fresco的优点:
1、Fresco最大的优势是在5.0以下系统的Bitmap加载,在5.0以下系统,Fresco将图片放置一个特别的内存区域(Ashmem区)。
2、大大减少OOM(在更底层的Native层对OOM进行处理,图片将不再占用App的内存)。
3、渐进式加载 JPEG 图片, 支持图片从模糊到清晰加载,尤其是慢网络有极大的利好,可带来更好的用户体验。
4、适用于需要高性能加载大量图片的场景。
Glide的缺点:
1、加载动图的情况下Java Heap比Fresco的高。
Fresco的缺点:
1、包比较大,是Glide的几倍大小。
2、API不够简洁,用法比较复杂。
3、底层设计C++ 领域,阅读及可开发性难度加大。
综上给出各图片库的使用建议是:
和Square的网络库配合使用最佳,因为他可以选择将网络请求的缓存部分交给Okhttp或者retrofit处理,如果项目中本来使用的网络库是Okhttp或者retrofit,并且没有Gif动图展示的情况下,Picasso无疑是个比较好的选择。
模仿了Picasso的链式调用等API,并且在其基础上做了大量的优化,比如支持Gif图片的加载;并且将图片格式由原来的A ARGB_8888改成了RGB_565,内存使用上减少了一半;将只支持缓存全尺寸图片的方式,优化成了不仅可以缓存全尺寸的图,还可以将根据ImageView大小生成的图片缓存起来。Glide功能强大,上手比较快,使用起来比较简单,配置也很方便。所以普通的APP建议使用Glide。
最大的优势是在5.0以下系统的Bitmap加载,在5.0以下系统,Fresco将图片放置一个特殊的区域(Ashmem区)。在图片不显示的时候,该特殊区域的内存会被释放,这会使得APP加载更加流程,减少因为图片内存占用而引发的OOM。为什么说是5.0以下,因为在5.0以后系统默认就是存储在Ashmem区了。Fresco在前人的基础上做了大量的优化,功能比较强大,图片缓存上也使用了三级缓存,是图片加载更加流畅,但是带来的问题就是包比较大,API使用起来比较复杂。所以只建议在专业的图片APP中使用。
参考:
https://cloud.tencent.com/developer/article/1385853
https://blog.fe.ioteams.com/post/image%2Fcontrast.html#toc-748