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

引子

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

Universal ImageLoader

Universal ImageLoader的缓存(MemoryCache)本质是一个LinkedHashMap

Android图片加载库内存缓存策略分析_第1张图片
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

Android图片加载库内存缓存策略分析_第2张图片
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中的资源一定没有被展示,因此可以对这些资源进行回收或复用等灵活的处理,从而减少了内存的占用,及时回收了可复用的内存资源。

你可能感兴趣的:(Android图片加载库内存缓存策略分析)