Android图片加载库内存缓存策略分析

引子

本文旨在横向分析Universal ImageLoader和Glide在内存管理上的区别,学习其中的技巧,开拓思路。

Universal ImageLoader

Universal ImageLoader的缓存(MemoryCache)本质是一个LinkedHashMap<String, Bitmap>

Universal ImageLoader

当图片通过网络或文件加载完成时,会将解码后的Bitmap存入memoryCache中。

当我们使用Universal ImageLoader加载图片时,根据URI和目标View的尺寸组成一个memoryKey,根据memoryKey我们在内存缓存(MemoryCache)中寻找相应的Bitmap。如果找到就直接显示;如果未能找到则需要走从文件缓存或从网络下载并解码的流程。

每当Universal ImageLoader从网络或文件中获取图片数据后,会将解码后的Bitmap放入MemoryCache中。如果MemoryCache,达到内存上限,我们会remove掉较早加入的Bitmap

**这里就是ImageLoader内存缓存缺陷的关键 ** :

至此,这个被我们remove掉的Bitmap,将离开我们的控制范围。我们既不能将它recycle掉,也不能将它复用。因为,此时这个被remove掉的Bitmap,还有可能被一个ImageView显示着。我们对它什么也不能做,只能等着某个ImageView不再显示它,然后等待系统的GC回收掉这个Bitmap

Universal ImageLoader的内存缓存缺陷:

我们无法判断内存缓存中的Bitmap,是否正被ImageView显示着,导致我们无法对离开缓存的Bitmap做任何操作,只能放任它被系统自动回收。


Glide

Glide缓存流程

我们第一遍从生成EngineKey那一步开始看。我们可以看到Glide将内存缓存分成了两层。分别为Active和Memory。Glide先从Memory后从Active中寻找,有没有想要的资源,如果找到就可以直接显示。在没有资源的情况下,Glide会开始加载解码的任务。

Glide的改进关键点在解码任务完成后 Glide将解码完成的图片与目标ImageView绑在了一起,同时,将这个图片的弱引用,以cacheKey为Key存入了active。

在这个过程中,我们没有将图片放入memory中。但此时图片不会被回收。因为ImageView还显示着这个图片。

那么,图片是何时被放入memory中呢?

从上面的流程图中,我们可以看到,图片被放入memory的时机其实在最开始。当我们用某一个ImageView加载图片时,我们首先会从View的tag中找到View已经绑定的资源,然后释放资源。在释放资源时,我们便会将这个不再需要显示的资源放入memory。

流程走到这里,虽然Glide的流程麻烦很多,但是还没有产生实际的效果。

接下来Glide是真正的优化:如果我们将资源放入memory中时,memory已满。此时,我们的操作就变的非常灵活了。因为,此时memory中所有的图片都是没有被展示的。我们可以将我们认为不重要的资源回收,或拿去复用。

总结:

相较于Universal ImageLoader朴实的使用LinkedHashMap,Glide将内存缓存分为了两层(active&memory)。同时,用tag将资源与ImageView绑定。通过这种方式,Glide确保了memory中的资源一定没有被展示,因此可以对这些资源进行回收或复用等灵活的处理,从而减少了内存的占用,及时回收了可复用的内存资源。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端架构

再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询、监听用户事件。

292
来自专栏ThoughtWorks

JavaScript是如何处理事件?

#思特沃克好声音# (图片:网络) 想必大家都知道JavaScript一般都是在浏览器中执行,大家也知道可以通过事件调用JavaScript函数,可是大家清楚J...

2696
来自专栏全栈之路

关于真机测试的几点感悟

602
来自专栏前端架构

再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询、监听用户事件。

1.7K15
来自专栏Linux驱动

13.Linux键盘按键驱动 (详解)

在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标:        实现键盘驱动,让开发板的...

2155
来自专栏wym

什么是DC,什么是兼容性DC

DC全称为Device Content,翻译过来是“设备描述表”或者“设备上下文”。显示图片时都会用到,为什么呢?首先,没有一句C语言可以帮助我们在屏幕上显示图...

1301
来自专栏州的先生

Python GUI教程(十一):使用多线程保持GUI的响应

1732
来自专栏walterlv - 吕毅的博客

WPF 多线程 UI:设计一个异步加载 UI 的容器

2018-09-08 12:53

711
来自专栏性能与架构

浏览器的UI线程

所有用于更新用户界面的操作都是由浏览器的UI线程来完成 UI线程维护一个队列,把每个要更新UI的操作都做为一个任务添加到队列中,然后等UI线程空闲时再按顺序进...

2997
来自专栏更流畅、简洁的软件开发方式

分享一个基于jQuery的锁定表格行列的js脚本。

  网上也有很多锁定行列的方法,一个是使用css,另一个就是专门的控件附带有锁定的功能。css的大多数锁定行,而不能锁定列。好像看过园子里的司徒正美,写过一个用...

2256

扫码关注云+社区