文/吴玄玄 马旭平
图片加载已经成为Android开发中最基础的功能,图片加载OOM问题也一直困扰很多开发者,android开发者为了降低开发周期、难度以及减少OOM,越来越多开发者倾向于开源图片加载框架,开源图片加载框架已经占据了很大比例市场,Glide作为最近几年新兴的开源图片加载框架对Android图片加载起了不可忽视的作用。Glide是Google一位员工的作品,Glide完全是基于Picasso开源框架,沿袭了Picasso简洁的风格,但在此基础上该员工做了大量的优化与改进。
目前,android市场上的app大多已采用开源图片加载框架,例如: Fresco、Picasso、Glide等。Fresco是Facebook推出的一款用于Android应用中展示图片的强大图片加载框架,它提供了图片下载、渐进式加载、内存管理等功能,很大程度上把开发者从繁琐的图片管理中解放出来,但它只支持自己的控件。Picasso是Square公司出品的一款非常优秀的开源图片加载框架,是目前Android开发中很受欢迎的图片加载框架之一。Glide作为Google在泰国举行的谷歌开发者论坛上推出的开源图片加载框架,已被大多数开发者所接受。作为几种主流的开源图片加载框架,Glide、Picasso、Fresco对图片的处理各有千秋,本文主要通过对比分析Glide与其它两种开源图片加载框架差异。
图1:Fresco、Picasso、Glide库大小
本部分主要从引入库大小、加载图片占用内存大小、易用性三个方面对比分析Glide、Picasso、Fresco。
Glide、Picasso、Fresco作为主流开源图片加载框架对图片的加载支持是比较完美的,在使用Glide、Picasso、Fresco三者的库时,只需在dependencies中添加一行代码即可,但三者引入库的大小却大不相同,Fresco 0.12.0 版本库大小为16.78Mb,Picasso 2.71828版本库大小为106.4Kb ,Glide 4.9.0版本的库大小为403.01Kb。通过库大小的对比(如图1所示),发现Fresco库太过于庞大,若是应用要求简洁轻量,Fresco将不做考虑。
除此之外,Picasso的整个库可分为Dispatcher、Requesthandlery以 及Downloader、PicassoDrawable等 模 块。Picasso在收到加载以及显示图片的任务时,创建Request并将它交给Dispatcher,Dispatcher分发任务到具体RequestHandler,任务通过MemoryCache显示到Target中。
Glide整个库分为RequestManager(请求管理器)、Engine(数据获取引擎)、Fetcher(数据获取器)、MemoryCache(内存缓存)、Registry(图片类型及解析器配置)、Target(目标)等模块。当Glide收到加载及显示图片的任务时,创建Requset并将它交给RequesManager,Request启动Engine通过Fetcher获取数据资源,Transformation处理后交给Target。
Picasso库模块少于Glide,图片处理流程调用库模块较少,加载图片速度较快,若对图片加载速度有要求,Picasso会是首选。
Fresco加载图片时把图片放到一个特别的内存区(Ashmem区),当图片不显示的时候,占用的内存会自动释放,从而减少内存空间的占用,这会使应用更加流畅,减少因图片占用内存引发的OOM,但Fresco的图片加载用法太复杂,不适用于轻量型应用,故应用若是对大小有要求,不宜使用Fresco。Picasso加载图片采用的是ARGB-8888格式,Glide加载图片默认采用Bitmap格式RGB-565,由于加载格式的不同,导致Glide加载图片的质量不如Picasso,但Glide所占内存较小,即使是把Glide加载图片的格式调整为ARGB-8888,Glide、所占的内存仍远远小于Picasso。Picasso加载图片是加载全尺寸的图片到内存,然后让GPU实时重绘大小,而Glide加载图片的大小是和ImageView的大小一致的。
在加载图片这方面,Glide是优于Picasso的,Glide加载图片占用内存小,除此之外,Glide可以自动计算出任意情况下ImageView的大小,图片加载速度会更快,在上述这些方面Glide优于Picasso与Fresco。
在图片加载的易用性上,Glide与Picasso也是完胜Fressco的,大多数情况下Glide与Picasso图片加载只需一行代码即可,Fresco使用方法较复杂,代码量较多,在易用性方面较差。Glide与 Picasso非常相似,图片加载方式如出一辙,Glide的with()方法不止可以接受Content,还可以接受Fragment和Activity,最重要的是将Activity与Fragment作为with()参数图片加载会和Activity与Fragment的生命周期保持一致,有利于对资源进行管理。
本部分从引入库大小、加载图片占用内存大小、易用性等方面来分析不难发现Glide优于Picasso与Fresco。
Fresco、Picasso、 Glide作为主流开源图片加载框架,三者的缓存机制也是不同的。
Fresco采用的是三级缓存:
(1)Bitmap缓存:Bitmap对象可以立刻用来显示或者用于后处理;
(2)未解码图片的内存缓存:原始压缩格式的图片,从该缓存取到的图片在使用之前,需要先进行解码;
(3)文件缓存:文件缓存存储的是未解码的原始压缩格式的图片,在使用之前同样需要经过解码等处理。
Picasso自带两级缓存:内存缓存以及硬盘缓存。Picasso无本地缓存,它把此功能交给了Square 的另外一个网络库 okhttp 去实现,这样做的好处在于可以通过请求Response Header中的 Cache-Control及Expired控制图片的过期时间。
Glide加载图片使用的是四级缓存:
(1)资源缓存;
(2)内存缓存;
(3)磁盘缓存;
(4)文件缓存。
Glide在开始一个新的图片请求之前会检查多级缓存,首先,判断当前是否有正在展示的这张图片资源,若是有,则直接返回图片资源,无则到内存中检查是否存在;内存中若是存在则返回图片资源,无则判断图片是否写入过磁盘缓存;磁盘中若是存在则返回图片,无则检查是否写入过文件缓存;文件缓存若是存在则返回图片,无则直接到原始资源取回数据。
Glide的四级缓存使得其图片加载速度相比于Picasso与Fresco会快一些,另外四级缓存还可以减少对数据源的访问量,减轻服务器的压力。从缓存机制方面来分析,Glide会是图片加载框架更好的选择。
Android应用开发大多数是加载静态图片,而有的则需要加载动态图片即GIF。Glide、Fresco作为主流开源图片加载框架对GIF加载是完美支持的,而Picasso不支持显示GIF,在此技术方面Picasso将会被排除。若是应用无需加载GIF,则Picasso会是首选,因为Picasso包较小,相应的应用体积也会较小,并且图片加载质量也不差;反之若是需加载GIF,由于Fresco包较大,并且使用较复杂,Glide当为首选。除此之外,Glide内部会自动识别图片类型,不管我们传入的是一张普通图片还是一张GIF,Glide都会自动判别从而正确地把它解析并展示出来。加载GIF是Glide非常特色的一个功能,并且这个功能我们并不需要编写额外代码,在加载GIF方面来分析,GIF的加载Glide当为不二选择。
Glide除了支持加载GIF以外,还可以加载本地视频,这是其它开源图片加载框架所不具备的。Glide视频加载与图片加载类似,只需获得本地视频地址,并把load()参数设置为load(Uri.fromFile(newFile(filePath)))即 可,其中filePath是需加载的视频文件地址。Picasso与Fresco对此不支持,这是Glide的一大特色,若是应用需加载本地视频则优先考虑使用Glide。
Glide、Picasso、Fresco使用场景对比如图2所示。
Fresco虽然功能强大,但是包也很大,依赖很多,使用复杂,而且还要在布局使用SimpleDraweeView控件加载图片。除此之外,Fresco获取bitmap比较复杂,使用起来并不是那么方便,但它可以大大减少OOM,适用于需要高性能加载大量图片的场景,若是应用对体积无要求可以使用Fresco。另外,若是专业的图片应用,对图片质量等要求较高,Fresco也当为首选。
图2:使用场景分析
Picasso与Glide,Picasso所能做到的Glide也能做到,只是所需配置不同,但Picasso包体积比Glide小,而且图片质量高,若是无GIF加载、对图片质量要求较高且应用体积较小,则可以选择Picasso。
Glide作为Picasso的升级版,除了具有Picasso优点之外,还支持加载GIF,图片加载速度较快,若是需要处理大型的图片流,或者制作视频类应用,或者对图片的质量不是很注重,Glide当为首选。
除此之外,Glide对新手比较友好,上手快,使用简单,配置方便,对一般应用而言是不错的选择。
本文主要从图片加载、图片缓存、GIF加载、本地视频加载、使用场景等方面,通过Glide与Fresco、Picasso主流开源图片加载框架对比,对Glide开源图片加载框架进行分析,并通过分析说明Glide特点以及使用场景,供广大开源图片加载框架使用者参考。