文档章节

开源选型之 Android 三大图片缓存原理、特性对比

iSnowFlake
 iSnowFlake
发布于 2015/10/21 11:32
字数 2189
阅读 100
收藏 0
点赞 0
评论 0

这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事。


从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现。


略掉前面关于选择开源项目的好处及如何选择开源项目的部分(回复"开源项目"查看),进入重点。


一. 四大图片缓存基本信息

Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用。


Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所以广为人知。


Glide 是 Google 员工的开源项目,被一些 Google App 使用,在去年的 Google I/O 上被推荐,不过目前国内资料不多。


Fresco 是 Facebook 在今年上半年开源的图片缓存,主要特点包括:

(1) 两个内存缓存加上 Native 缓存构成了三级缓存


(2) 支持流式,可以类似网页上模糊渐进式显示图片


(3) 对多帧动画图片支持更好,如 Gif、WebP


鉴于 Fresco 还没发布正式的 1.0 版本,同时一直没太多时间熟悉 Fresco 源码,后面对比不包括 Fresco,以后有时间再加入对比。


二、基本概念

在正式对比前,先了解几个图片缓存通用的概念:

(1) RequestManager:请求生成和管理模块


(2) Engine:引擎部分,负责创建任务(获取数据),并调度执行


(3) GetDataInterface:数据获取接口,负责从各个数据源获取数据。

比如 MemoryCache 从内存缓存获取数据、DiskCache 从本地缓存获取数据,下载器从网络获取数据等。


(4) Displayer:资源(图片)显示器,用于显示或操作资源。

比如 ImageView,这几个图片缓存都不仅仅支持 ImageView,同时支持其他 View 以及虚拟的 Displayer 概念。


(5) Processor 资源(图片)处理器

负责处理资源,比如旋转、压缩、截取等。


以上概念的称呼在不同图片缓存中可能不同,比如 Displayer 在 ImageLoader 中叫做 ImageAware,在 Picasso 和 Glide 中叫做 Target。


三、共同优点

1. 使用简单

都可以通过一句代码可实现图片获取和显示。


2. 可配置度高,自适应程度高

图片缓存的下载器(重试机制)、解码器、显示器、处理器、内存缓存、本地缓存、线程池、缓存算法等大都可轻松配置。


自适应程度高,根据系统性能初始化缓存配置、系统信息变更后动态调整策略。

比如根据 CPU 核数确定最大并发数,根据可用内存确定内存缓存大小,网络状态变化时调整最大并发数等。


3. 多级缓存

都至少有两级缓存、提高图片加载速度。


4. 支持多种数据源

支持多种数据源,网络、本地、资源、Assets 等


5. 支持多种 Displayer

不仅仅支持 ImageView,同时支持其他 View 以及虚拟的 Displayer 概念。


其他小的共同点包括支持动画、支持 transform 处理、获取 EXIF 信息等。


四、ImageLoader 设计及优点


1. 总体设计及流程

上面是 ImageLoader 的总体设计图。整个库分为 ImageLoaderEngine,Cache 及 ImageDownloader,ImageDecoder,BitmapDisplayer,BitmapProcessor 五大模块,其中 Cache 分为 MemoryCache 和 DiskCache 两部分。


简单的讲就是 ImageLoader 收到加载及显示图片的任务,并将它交给 ImageLoaderEngine,ImageLoaderEngine 分发任务到具体线程池去执行,任务通过 Cache 及 ImageDownloader 获取图片,中间可能经过 BitmapProcessor 和 ImageDecoder 处理,最终转换为Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。


2. ImageLoader 优点

(1) 支持下载进度监听


(2) 可以在 View 滚动中暂停图片加载

通过 PauseOnScrollListener 接口可以在 View 滚动中暂停图片加载。


(3) 默认实现多种内存缓存算法

这几个图片缓存都可以配置缓存算法,不过 ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等。


(4) 支持本地缓存文件名规则定义


五、Picasso 设计及优点


1. 总体设计及流程

上面是 Picasso 的总体设计图。整个库分为 Dispatcher,RequestHandler 及 Downloader,PicassoDrawable 等模块。


Dispatcher 负责分发和处理 Action,包括提交、暂停、继续、取消、网络状态变化、重试等等。


简单的讲就是 Picasso 收到加载及显示图片的任务,创建 Request 并将它交给 Dispatcher,Dispatcher 分发任务到具体 RequestHandler,任务通过 MemoryCache 及 Handler(数据获取接口) 获取图片,图片获取成功后通过 PicassoDrawable 显示到 Target 中。


需要注意的是上面 Data 的 File system 部分,Picasso 没有自定义本地缓存的接口,默认使用 http 的本地缓存,API 9 以上使用 okhttp,以下使用 Urlconnection,所以如果需要自定义本地缓存就需要重定义 Downloader。


2. Picasso 优点

(1) 自带统计监控功能

支持图片缓存使用的监控,包括缓存命中率、已使用内存大小、节省的流量等。


(2) 支持优先级处理

每次任务调度前会选择优先级高的任务,比如 App 页面中 Banner 的优先级高于 Icon 时就很适用。


(3) 支持延迟到图片尺寸计算完成加载


(4) 支持飞行模式、并发线程数根据网络类型而变

手机切换到飞行模式或网络类型变换时会自动调整线程池最大并发数,比如 wifi 最大并发为 4, 4g 为 3,3g 为 2。


(5) “无”本地缓存

无”本地缓存,不是说没有本地缓存,而是 Picasso 自己没有实现,交给了 Square 的另外一个网络库 okhttp 去实现,这样的好处是可以通过请求 Response Header 中的 Cache-Control 及 Expired 控制图片的过期时间。


六、Glide 设计及优点

1. 总体设计及流程

上面是 Glide 的总体设计图。整个库分为 RequestManager(请求管理器),Engine(数据获取引擎)、 Fetcher(数据获取器)、MemoryCache(内存缓存)、DiskLRUCache、Transformation(图片处理)、Encoder(本地缓存存储)、Registry(图片类型及解析器配置)、Target(目标) 等模块。


简单的讲就是 Glide 收到加载及显示资源的任务,创建 Request 并将它交给RequestManager,Request 启动 Engine 去数据源获取资源(通过 Fetcher ),获取到后 Transformation 处理后交给 Target 。


Glide 依赖于 DiskLRUCache、GifDecoder 等开源库去完成本地缓存和 Gif 图片解码工作。


2. Glide 优点

(1) 图片缓存->媒体缓存

Glide 不仅是一个图片缓存,它支持 Gif、WebP、缩略图。甚至是 Video,所以更该当做一个媒体缓存。


(2) 支持优先级处理


(3) 与 Activity/Fragment 生命周期一致,支持 trimMemory

Glide 对每个 context 都保持一个 RequestManager,通过 FragmentTransaction 保持与 Activity/Fragment 生命周期一致,并且有对应的 trimMemory 接口实现可供调用。


(4) 支持 okhttp、Volley

Glide 默认通过 UrlConnection 获取数据,可以配合 okhttp 或是 Volley 使用。实际 ImageLoader、Picasso 也都支持 okhttp、Volley。


(5) 内存友好

(1) Glide 的内存缓存有个 active 的设计

从内存缓存中取数据时,不像一般的实现用 get,而是用 remove,再将这个缓存数据放到一个 value 为软引用的 activeResources map 中,并计数引用数,在图片加载完成后进行判断,如果引用计数为空则回收掉。


(2) 内存缓存更小图片

Glide 以 url、view_width、view_height、屏幕的分辨率等做为联合 key,将处理后的图片缓存在内存缓存中,而不是原始图片以节省大小


(3) 与 Activity/Fragment 生命周期一致,支持 trimMemory


(4) 图片默认使用默认 RGB_565 而不是 ARGB_888

虽然清晰度差些,但图片更小,也可配置到 ARGB_888。


其他:Glide 可以通过 signature 或不使用本地缓存支持 url 过期



    七、汇总


    三者总体上来说,ImageLoader 的功能以及代理容易理解长度都一般。


    Picasso 代码虽然只在一个包下,没有严格的包区分,但代码简单、逻辑清晰,一两个小时就能叫深入的了解完。


    Glide 功能强大,但代码量大、流转复杂。在较深掌握的情况下才推荐使用,免得出了问题难以下手结局。



    本文转载自:http://mp.weixin.qq.com/s?__biz=MzAxNjI3MDkzOQ==&mid=400056342&idx=1&sn=894325d70f16a28bfe8d6a4da...

    共有 人打赏支持
    iSnowFlake
    粉丝 32
    博文 80
    码字总数 53599
    作品 0
    深圳
    高级程序员
    Glide ‘优’ 与 ‘愁’

    随着业务的增长,加载图片是不可避免的需求。从一开始的自己写一个 ImageLoader 到井喷似的第三方图片加载库,当然中间还时不时穿插着 asynctask ,三级缓存,LRU Cache等。那个时候想必大家...

    IMSk ⋅ 06/20 ⋅ 0

    [干货]2017已来,最全面试总结——这些Android面试题你一定需要

    相关阅读: 吊炸天!74款APP完整源码! [干货精品,值得收藏]超全的一线互联网公司内部面试题库,有了它,妈妈再也不用担心我进不了大公司了! [干货,阅后进BAT不是梦]面试心得与总结---BA...

    xhmj12 ⋅ 2017/01/25 ⋅ 0

    腾讯技术分享:Android版手机QQ的缓存监控与优化实践

    本文内容整理自公众号腾讯Bugly,感谢原作者的分享。 1、问题背景 对于Android应用来说,内存向来是比较重要的性能指标。内存占用过高,会影响应用的流畅度,甚至引发OOM,非常影响用户体验。...

    JackJiang2011 ⋅ 04/08 ⋅ 0

    2018 Android 面试心得,已拿到 offer

    code小生,一个专注于 Android 领域的技术分享平台 作者:huisonma 链接:https://www.jianshu.com/p/855ff21e0a13 声明:本文是 huisonma 原创,转发等请联系原作者授权。 从 16 年毕业至今...

    h176nhx7 ⋅ 04/16 ⋅ 0

    Android Bitmap变迁与原理解析(4.x-8.x)

    App开发不可避免的要和图片打交道,由于其占用内存非常大,管理不当很容易导致内存不足,最后OOM,图片的背后其实是Bitmap,它是Android中最能吃内存的对象之一,也是很多OOM的元凶,不过,在...

    看书的小蜗牛 ⋅ 05/22 ⋅ 0

    【社招】招聘高级多媒体工程师-一家拥有15亿用户量的出海互联网企业

    感兴趣的小伙伴请加我微信(2200624973) 岗位职责: 1、参与或者独立承担 Android 平台上媒体处理相关功能的设计、实现、测试及功能维护,参与或者独立承担方案或者架构选型。 2、参与产品的...

    弓小嘿 ⋅ 05/17 ⋅ 0

    安卓巴士Android开发者门户

    一、开源库 1.SimpleRatingBar 简单好用的ratingbar 2.NumberRain Android自定义控件仿黑客帝国数字雨 3.CacheWebView 突破系统WebView缓存的空间限制的WebView 4.lucklypopupwindow Android...

    迷你芊宝宝 ⋅ 前天 ⋅ 0

    Android 性能优化:手把手教你优化Bitmap图片资源的使用

    前言 在 开发中,性能优化策略十分重要 本文主要讲解性能优化中的Bitmap 使用优化,希望你们会喜欢 目录 1. 优化原因 即 为什么要优化图片资源,具体如下图:

    Carson_Ho ⋅ 04/24 ⋅ 0

    最美应用-从Android研发工程师的角度之[最美时光]

    最美应用-从Android研发工程师的角度之最美时光 @author ASCE1885的 Github 简书 微博 CSDN 最近发现最美应用这样一个网站,它会定期推介一些很有意思的app,作为开发者,每次看到很棒的app...

    小树coding ⋅ 2015/08/19 ⋅ 0

    《App架构师实践指南》:移动开发的进阶指南

    文章主要内容: 什么是 app 架构师 这本书主要内容 读完感受 什么是 App 架构师 成为“架构师”是许多程序员的梦想,当然也包括我,在工作的几年里,我见过很多架构师,他们在设计某个大型系...

    异步社区 ⋅ 05/29 ⋅ 0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    Python爬虫,抓取淘宝商品评论内容

    作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿“德州扒鸡”...

    python玩家 ⋅ 6分钟前 ⋅ 0

    MySQL 内核深度优化

    MYSQL数据库适用场景广泛,相较于Oracle、DB2性价比更高,Web网站、日志系统、数据仓库等场景都有MYSQL用武之地,但是也存在对于事务性支持不太好(MySQL 5.5版本开始默认引擎才是InnoDB事务...

    java高级架构牛人 ⋅ 28分钟前 ⋅ 0

    用户登录信息-钉子效果(基于jquery2.0)

    本js效果使用jquery2.0,清晰的分解用户登录信息的(钉子效果),该效果直接用在作者网站(www.phpkhbd.com)上。 里面的难点有:定时器,延时。 大致效果如下: 一开始: 鼠标放上去的时候:...

    宁哥实战课堂 ⋅ 30分钟前 ⋅ 0

    解决yum安装报错Protected multilib versions

    使用yum安装报错Protected multilib versions原因是因为多个库不能共存,不过更新的话也并不行,但是可以在安装命令后面加上如下一段命令: --setopt=protected_multilib=false 案例: 比如需...

    北岩 ⋅ 41分钟前 ⋅ 0

    为什么要学习Typescript???

    简单来说 目前的typescript就是未来的javascript 为什么?? 这要从ECMA-262标准的第4版说起 对了 我们说的ES5 其实是ECMAScript3.1这个替代性建议被扶正了而已... 那么 第4版标准是什么? 看看...

    hang1989 ⋅ 45分钟前 ⋅ 0

    linux安装ipfs

    一、下载ipfs # cd /usr/local/ipfs/ # wget https://dist.ipfs.io/go-ipfs/v0.4.15/go-ipfs_v0.4.15_linux-amd64.tar.gz # tar -zxvf go-ipfs_v0.4.15_linux-amd64.tar.gz 二、安装ipfs # ......

    八戒八戒八戒 ⋅ 51分钟前 ⋅ 0

    jvm程序执行慢诊断手册

    生产环境最多的几种事故之一就是程序执行慢,如果是web服务的话,表现就是响应时间长。本文分享,从业多年形成的排查守则。 诊断步骤 系统资源查看 首先是系统资源查看,而且必须是在第一步。...

    xpbob ⋅ 51分钟前 ⋅ 0

    YII2 advanced 高级版本项目搭建-添加API应用以及多应用

    一、YII安裝 安裝yii可以用composer安裝,也可以在yii中文社区下载归档文件安装 composer安装就不介绍了,因为要安装composer,比较麻烦,当然安装了composer是最好的,以后安装yii的插件要用...

    botkenni ⋅ 52分钟前 ⋅ 0

    在jdk1.8的环境下模拟永久代内存溢出

    相信不少小伙伴在看深入理解Java虚拟机的时候,作者给我们举例一个demo来发生PermGen space 1、通过List不断添加String.intern(); 2、通过设置对应的-XX:PermSize与-XX:MaxPermSize(更快看到...

    虾几把写 ⋅ 今天 ⋅ 0

    开发OpenDaylight组件的完整流程

    在前面介绍学习了OpenDaylight的几个重要模块后,这里再来介绍下完整开发一个模块的过程。 OSGI的bundles提供被其他OSGI组件调用的服务。这个教程中展示的是Data Packet Service去解析数据包...

    wangxuwei ⋅ 今天 ⋅ 0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    返回顶部
    顶部