Glide 系列(一) 图片加载框架对比

本文主要比对框架包括:Universal Imageloader(下文简称 UIL)、Picasso、 Glide、Fresco。先对各个框架做简单介绍,再对框架进行对比。

简介篇

UIL

UIL 是一个老牌的图片加载框架,旨在提供一个强大的、灵活的和高度可定制的工具,以实现图像加载、缓存和显示功能。
UIL 支持多线程图片加载,支持占位图和错误图、支持图片下载进度的监听,支持缓存不同尺寸图片,支持图片内存缓存和硬盘缓存,支持自定义图片加载格式,支持 ListView或者 GridView 滚动时暂停加载。但 UIL 不支持动图展示,且该框架的作者已经宣布不在对其进行维护。

ImageLoader.getInstance()
.displayImage("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg", ivImg, null);
Picasso

Picasso 其名字来源于画家毕加索,是著名开源公司 Square 的作品,与 OkHttp 和 Retrofit 合称开发三件套。Picasso 同样支持占位图和错误图展示,支持图形变换操作,支持内存和硬盘缓存,支持加载本地或者网络资源,比较有特色的是其拥有统计功能,可以知道一共使用了多少内存,缓存命中率, 图片来自内存还是硬盘等。Picasso 使用起来也是简单方便,基本上一行代码可解决显示图片请求。

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

Glide 是一个 Google 官方推荐的快速高效的图片加载库,主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑。
Glide 提供了简单易用的API,典型流式语法风格,大部分展示图片需求可以一行代码搞定。Glide 的 API 还特别灵活,在支持开发者自定义配置和模块的同时又和其图片加载图片的逻辑没有任何交集,是一种低耦合的编程方式的实现。默认情况下,通信组件使用 HttpUrlConnection,但也提供了 Volley 和 OkHttp 快速集成的工具。

Glide.with(fragment).load(url).into(imageView);

Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:

  • 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
  • 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
  • 深度的生命周期集成,以确保仅优先处理活跃的 Fragment 和 Activity 的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

生命周期的集成也是 Glide 的一大特色。

Fresco

Fresco 是一个强大的图片加载组件,其设计中有一个叫做 Image Pipeline 的模块,负责从网络、本地文件系统、本地资源加载图片。为了最大限度节省空间和CPU时间,它含有 3 级缓存设计(2级内存,1级磁盘)。还有一个叫做 Drawees 的模块,它会在图片加载完成前显示占位图,加载成功后自动替换为目标图片。当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。

Fresco 包含以下特性:

  • 内存管理:在 Andrid 5.0 以下系统,Fresco 会将图片放到 ASM(Anonymous Shared Memory,匿名共享内存)区域,减少了低性能手机上 OOM 的发生。在图片不用时,应该显式释放这部分资源,SimpleDraweeView 自动处理了这个释放过程。在 5.0 及以上版本系统,由于 Android 对其内存管理做了很大优化,Bitmap 缓存位于 Java 堆区,同样避免了 OOM 的发生。
  • 图片加载:Image Pipeline 允许你用多种方式来定义图片的加载过程图片可以来自远程服务器,本地文件,或者Content Provider,本地资源。压缩后的文件缓存在本地存储中,Bitmap数据缓存在内存中。
  • 图片绘制:可自定义占位图或者进度条,自定义 overlay,现在失败后的点击重试等。
  • 图片渐进式呈现:Android 本身的图片库不支持此格式,但是Fresco支持渐进式图片。渐进式格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验。
  • 友好的支持 Gif 图片和 Webp 动图。

Fresco 使用时需要用其框架定义的组件,且明确指定尺寸 或者用 match_parent 标注。

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/my_image_view"
    android:layout_width="130dp"
    android:layout_height="130dp"
    fresco:placeholderImage="@drawable/my_drawable"
  />
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);

对比篇

共同特性
  • 支持占位图或者加载错误图
  • 支持 图像变换,如 裁剪、尺寸修改、方圆转换等
  • 可配置度高,图片缓存的内存缓存、本地缓存、线程池、缓存算法等大都可轻松配置。
  • 自适应程度高,根据系统性能初始化缓存配置、系统信息变更后动态调整策略。比如根据 CPU 核数确定最大并发数,根据可用内存确定内存缓存大小,网络状态变化时调整最大并发数等。
  • 多级缓存,都至少有二级缓存,提高图片的加载速度
  • 支持多种数据源,如网络、本地、Assets等
  • 支持多种 Displayer,支持自定义的 Displayer 概念。
  • 支持配置图片格式,如配置 ARGB_8888、RGB_565 等
对比表格
对比图.png
磁盘缓存

我们先啰嗦两句,来看一下存储器的层次结构,简单分为:寄存器、高速缓存、主存、本地磁盘。


存储器层次模型.jpg

此图由上到下数据访问速度在逐层降低,从内存读取数据的速度远远大于从硬盘读取数据,从硬盘读取数据的速度远远大于从网络访问数据的速度,且网络访问还有可能失败。寄存器、高速缓存这两层对于我们 app 开发者来说是透明的,无需考虑,我们只需将内存缓存和硬盘缓存利用起来就可以了。基本上所有的图片加载框架都是在内存和硬盘这两个层次上做的数据缓存。内存缓存作为第一级缓存,可以避免将同一张图片重复加载到内存;硬盘缓存作为第二级缓存,可以避免重复下载同一张网络图片。

我们知道 ImageView 在显示图片时只是起一个容器的作用,里面放置的图片是 一个由像素组成的二维矩阵。既然是一个容器,那图片大小可能大于容器,也可能小于容器,所以才有了 ImageView 的 scaleType 属性。当图片大于容器时,可以将图片压缩,裁剪;当图片小于容器时既可以放大填充容器,也可以不做任何事情。且图片在硬盘中的大小并不等于在内存中的大小。图片在内存中的大小取决于其编码格式。许多图片加载框架会根据 ImageView 大小对图片做缩略处理,这样既保证了清晰度又减少了内存耗用。

全尺寸 指 url 对应的图片,实际尺寸为 ImageView 尺寸相同的图片。对于 Picasso,不管 ImageView 如何变换大小,只会缓存一个全尺寸的图片。对于 Glide、UIL、Fresco 都支持缓存同一图片的不同尺寸。对同一张图片缓存不同尺寸意味着需要更大的缓存空间,但同时也能提供了更快的展示速度,此处就是用空间换取时间,省去了每次显示之前将图片重新调整大小的时间。所以缓存多尺寸的图片框架会相较于缓存原始尺寸的更加快,但由于占据了更多的空间,这一点可以按需设置。

图片格式

不论采用哪个框架,同一张图片其显示质量取决于图片在内存中的格式,与框架无关。这四个框架都支持配置图片格式。格式清晰度从高到低如下:

ARGB_8888 >RGB_565 > ARGB_4444 >ALPHA_8

附:在这对图片格式做一个简单介绍:其中 A,代表透明度;R,代表 Red, 红色;G,代表 Green,绿色;B,代表 Blue,蓝色。

  • ALPHA_8,代表像素只有透明度信息,没有颜色信息,一个像素占 8 bit,即 1 Byte。
  • RGB_565,代表像素只有颜色信息,没有透明度信息,其中 R 占用 5 bit,G 占用 6 bit,B 占用 5 bit,一个像素大小为 5+6+5=16 bit ,即 2 Byte。
  • ARGB_4444,代表像素既有透明度信息,也有颜色信息,其中 A 占用 4 bit,R 占用 4 bit,G 占用 4 bit,B 占用 4 bit,一个像素大小为 4+4+4+4=16 bit ,即 2 Byte。
  • ARGB_8888,代表像素既有透明度信息,也有颜色信息,其中 A 占用 8 bit,R 占用 8 bit,G 占用 8 bit,B 占用 8 bit,一个像素大小为 8+8+8+8=32 bit ,即 4 Byte。

这几个字段在 Android 源码 Bitmap.Config 有中定义,可以看到 ARGB_8888 格式 是占用空间最大的,一个像素点要占用 4 Byte 内存,由于保存了更多的图片细节信息,所以此格式也是显示图片最清晰的。ARGB_4444 和 RGB_565 占用内存为 ARGB_8888 的一半。ARGB_4444 虽然设计理念是为了保留透明度的同时又节省内存,但由于其显示的图像质量太差而遭到弃用。RGB_565 和 ARGB_8888 是最为通用的两种图片格式,可以按需选取。如果必须保留图片的透明度信息,则建议使用 ARGB_8888, 如果APP 内存吃紧同时对透明度没有要求的话,可使用 RGB_565。

包体积

UIL 和 Picasso 包体积较小,对安装包影响不大。
Glide 包体积略大,其功能十分强大,内部实现及其复杂,其方法数较多,使用时可能会遇到 65k 问题。
Fresco 包体积很大,若按照正确步骤使用了 Fresco,引入后发布包的体积应当不会增加 500Kb。用户可以根据自己需求有选择的添加动画依赖库和 WebP 支持包,这种模块化机制使得基础 Fresco 库很轻,增加一个库大约包体积会增加 100 KB。

如何选择图片加载框架

UIL:建议弃用,除非你的项目一直在用 UIL 且框架迁移成本(时间成本)比较大。否则不建议使用或沿用,因为官方已经不再对其维护,且由于不支持动图,若 app 有动图支持的话还需引入其他图片框架,增加应用体积,还不如一步到位。

Picasso:不建议使用,Glide 是 Picasso 的加强版,可以说它的目的就是为了取代 Picasso,所以在 Glide 和 Picasso 之间选择,优先推荐 Glide 。

Glide vs Fresco:这两个框架性能不分伯仲,都可以减少 OOM 的发生。Glide 注重于平滑的滚动,善于处理大型的图片流,Glide还支持播放短视频,有此需求的话 Glide 为不二之选,另外 Glide 还有一个隐藏的优点,它是 Google 官方推荐的框架,所以相对于后期维护成本来说更低一些。Fresco 的优点是内存管理,尤其是在 5.0 以下的系统中优化做的非常好,将图片放在 ASM 中。其缺点也很明显,包的体积太大,其在图片多的应用中更能体现其价值。Fresco 对代码的侵入性可能会更高一些,由于所有的View 组件需要继承自一个基类 DraweeView ,需指定明确尺寸或者用 match_parent 来布局(为了更好的用户体验,解决占位图和真实图尺寸大小不匹配导致UI跳跃的问题),如果你是一个新项目,可以考虑用 Fresco。

总结:框架只在Glide 和 Fresco 中选择,Glide 是 Google 官方推荐的框架,是开发者的首选。如果你对包体积没有要求,且图片需求特别多的情况推荐使用 Fresco。

附:

http://blog.csdn.net/zivensonice/article/details/51822968
http://www.mamicode.com/info-detail-929571.html
这两个链接是对各个框架加载图片时堆内存、本地内存、加载时间、请求次数的对比,有兴趣的可以自己参考下。笔者个人感觉参考性不是很大,在多个机型测试结果不稳定,及同机型上框架切换时数据变化慢。现在 Android Studio 3.0 版本有 Android Profiler,可以点开观察内存情况,这个只支持5.0版本以上的手机哦。

参考文献

https://www.fresco-cn.org/
https://github.com/bumptech/glide/wiki
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2650.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容