图片加载理解之 UIL

针对Android 的图片加载,有着太多的细节问题,需要注意,本文针对 Universal Image Loader 的一些技术点,进行细致的剖析一番。由于涉及的内容,所以打算分成三个系列,分别从视图(View),数据(Cache),网络等三个大的方面讲起:

视图

1. ImageLoader是如何实现对ImageView的包装的?

1)ImageAware:针对 ImageView 行为的抽象--接口,获取 ImageView 的宽度、高度、scaleType、id;以及包装的ImageView,设定图片;
2)ViewAware: 抽象类,实现ImageAware。提供了ViewRef的属性,来持有ImageView的弱引用;实现方式:this.viewRef = new WeakReference<View>(view)。

使用弱引用的目的,避免了异步耗时任务对 ImageView 的强引用,能够使 ImageView 能够被及时回收,防止内存泄露的发生(虽然很短暂的一瞬间)。

2. 在 ListView 加载显示图片的时候,当一个正在加载图片的 View 被滑出屏幕,ImageLoader 是否会取消此次下载图片任务,是如何取消的?

首先在加载获取图片时,是通过 ImageLoaderEngine 来进行提交进行的。在 ImageLoaderEngine 是启动线程池来异步加载图片,分别从内存、磁盘、网络中进行获取。而在这几步之前,会首先进行 View 是否被回收的判断,若是被回收,则抛出异常,并调用相应 listener 的 cancel 方法。

3. 在 ListView 的滑动过程中,如何暂停所有的图片加载任务?

在 ImageLoader 中,其提供了一个 PauseOnScrollListener 的类,在使用 ListView 的时,只需进行设置即可。

其实现原理则是在通过调用 ImageLoader 的 pauseresume 方法,在调用图片加载的第一步会进行判断,是否设置了暂停状态,如果设置了,则会通过对象锁 pauseLock 的 wait 方法,来使当前图片加载线程处于阻塞状态;当调用了 resume 方法,则会调用了 pauseLock 的 notifyAll 方法,来恢复线程的执行。

这样做的作用是达到 CPU 资源的充分利用,通过暂停异步图片加载的线程,来不使 UI 线程卡顿,提高 ListView 在滑动过程的流畅程度。

4. 怎样针对 View 的特定大小,处理获取到图片的大小?

在 ImageLoader 调用 displayImage 方法时,在指定相应的 ImageView 时,也可以传递一个 ImageSize 的参数,用来指定所需显示的图片的大小;若是不传的话,则会获取 ImageView 的 width 及 height,若获取到的值为 0,那么这个相应 ImageSize 的宽与高则会取屏幕的宽与高。

另外,在对图片进行缓存时,生成相应的缓存 Key 的值是根据图片的 uritargetSize (指定的图片大小)来生成的,所以,不同大小的 ImageView 获取到的 bitmap 则是不同的,即从缓存中拿到的是不同的。

这里,可以看出相应大小的 ImageView 与内存的缓存中的不同的 bitmap 是相对应的。而 diskCache 中则是以 uri 为键值的磁盘文件。另外,由磁盘文件转换为相应的 bitmap 则是对应下面问题的答案。

5. 图片是如何进行压缩的?

我们知道图片加载到内存之中,是以 Bitmap 的形式存在的。而在 Android App 中,内存是非常稀缺的资源。所以当加载大图片时,需要根据当前显示图片的控件,采用相应手段,只在内存中加载出来相应大小的 Bitmap ,来避免 Out Of Memory 的发生。

这里采用 BitmapFactory 来进行图片文件转换至 Bitmap 对象,通过其 decodeStream 方法,若是我们传递的参数 Options,其指定了 inJustDecodeBounds 为 true, 则只会获取图片的大小(并不会生成 Bitmap 对象),其输出值为 Options 对象的 outWidthoutHeight

根据获取到的图片大小,以及我们要显示图片的 View 的大小,便可计算出我们需要对图片进行缩放的比例,即指定 Options 参数的 inSampleSize 的值。(此时 inJustDecodeBounds 的值为 false)这样获取到的 Bitmap 对象就是进行缩放调整过的图像。

这一步便是 Android 中调整 Bitmap 大小,减少内存消耗关键性的一步。

数据

数据主要体现在对图片的缓存处理。UIL 对图片的缓存为三级缓存,一是内存,二是磁盘,三是网络(远程的服务器)。

在内存中保存的为 Bitmap 对象,其是根据相应的 View 和 View 大小为 Key 值的。即加载的是同一张图片的两个不同大小的 View,会在内存缓存中存在针对这张图片的两个 Bitmap 对象。而磁盘中缓存的则只有这一张图片文件,即从远程服务器中下载到本地的图片文件。

若是本地磁盘中没有响应的图片文件的话,则会通过网络从远程服务器中下载图片至本地。

网络

从网络中获取图片,UIL 使用的是 HttpURLConnection,来执行图片的获取下载。对应逻辑代码是在 ImageLoader 接口中,其定义了由图片 imageUri,来得到 InputStream 。另外以指定 Scheme 的方式(如 HTTP,FILE,ASSETS,DRAWABLE) 来得到图片的输入流。

总结

UIL 作为图片加载的入门库,其逻辑代码也是写的非常漂亮。结构化清晰,简单明了,对各个模块都由一个接口来定义,极大地丰富细节的实现,像不同的内存、磁盘缓存策略及图片下载获取方式,另外这些策略都可以在 ImageLoader 的配置策略进行修改。总之,这个库是一个不错的学习 Android 图片加载的资料。

参考资料

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

推荐阅读更多精彩内容