Android 开发中需要处理图片的地方很多,但如何针对 Android 平台的特性,将图片这件不简单的事情,做到顺滑流畅则没那么简单。今天就分析下,Google 推荐的 Glide 开源框架,看看这个框架如何做好这件不简单的事情。
Glide 为什么优秀?
首先来分析下,一个优秀的图片库应该具有什么样的特性?
- 易用性。这对于绝大多数开源库而言,都是需要做到的,但这又是很难的一方面。举个例子,图片库涉及到网络、缓存、编码等等各个环节,但这些环节不应该让所有用户都知晓,应该拿捏到这种力度:用户可以不知晓,有需求的可以进行自定义。开源库可能有很多类用户可以涉及,但最好有统一的外观(Facade Pattern),Glide 在这点上就做得足够好。
- 扩展性。需求这东西嘛,总是比天气变化快多了,设计的开源库就必须得有很好的扩展性。无论是 Volley,Glide 还是其他知名开源库,在这点上都做得很好。关键在于抽象::不变的与变化的::,变化的是
网络
,编码
和缓存
等等模块,不变的是它们之间是如何衔接的。在合理的抽象建模下,还是很容易高的扩展性的。 - 高性能与低占用。这是图片库最核心的部分,也是最难的部分。难点在于三个方面。
- 内存受限。受限于移动终端的低内存,如果占用内存过大,会使得分配变得低效,不稳定。如果复用不给力,高频率的分配内存,会导致GC频繁,从而卡顿。
- 流畅性。Android 系统中的图片常用于 RecyclerView,GridView 中,这些控件往往展示着大量的图片,在这些图片频繁加载、编码等等情况下,保证滑动流畅呢?
- 生命周期。Android的UI组件有各个周期,Glide 要在尽可能少入侵代码的前提下,参与到生命周期里面去,从而合理地分配和释放资源。
Glide 如何做到易用性的?
本节和后序的章节,暂不涉及具体的源码,后续的文章再做分析。要想要让 Glide 易用,主要还是在 API 的设计上面。这里提出一个概念,链式调用
,是指一些方法能够直接通过.
的形式进行连接。
Glide.with(this).load(url).placeholder(resId).error(resId).into(mImageView);
上面的代码就是一个链式调用的例子,将 Glide 需要配置的地方,用一行代码就可以表达出来。我们常见的 RxJava、Java Builder 等等都采用了这种方式。
除了链式调用以外,Glide 的易用性,还提现在完善的职能模块,简单明了的接口。用户可以根据自身的需要进行自定义,也可以使用默认的方案。
如上图所示,Glide 将用户能够自定义的内容,都通过模块和相应的接口暴露出来,开发者可以根据自身需要,只对部分模块进行自定义即可。
Glide 如何实现高的扩展性?
高的扩展性前提就是清晰的模块划分,只有在这种情况下,模块才能进行插拔
和替换
,从而实现扩展性。
Glide 在大体上划分为Request
、Cache
、Module
、Decode
等等模块,统一由Registry
进行管理。在这个基础上,Glide 就能实现很好的扩展性。例如 Request
模块,即可以使用默认的,也可以使用Volley
或者OKHttp
。
Glide 如何实现好的性能?
Glide 的性能方面的掌控,主要由三个方面来实施的。
- 良好的复用模块。这是最核心的部分,当这块内存能够不断地被循环使用,能减少 GC 和分配的次数。内存操作一般情况下,都是 Stop the world 的,UI 线程也会因此中断,因而这对 APP 的性能极为关键。复用手段包括,但不止
LruCache
、Object Pool
。 - 本地化的生命周期。对于图片资源的释放,很少在保证即时性的情况下,又不需要开发者感知的。Glide 通过一个小技巧达成了目的,后续文章具体介绍哈。
- 对 RecyclerView 等等控件的细节调优。不要小看这些细节,罗马就是这么搭建出来的,抠的这些小细节,才是大师所为。
文档信息
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
- 发表日期:2017年10月22日
- 社交媒体:weibo.com/woaitqs
- Feed订阅:www.woaitqs.cc/feed.xml