美文网首页Android开发程序员Android开发
Android图片加载库内存缓存策略分析

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

作者: oceanLong | 来源:发表于2017-04-25 10:29 被阅读187次

    引子

    本文旨在横向分析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中的资源一定没有被展示,因此可以对这些资源进行回收或复用等灵活的处理,从而减少了内存的占用,及时回收了可复用的内存资源。

    相关文章

      网友评论

        本文标题:Android图片加载库内存缓存策略分析

        本文链接:https://www.haomeiwen.com/subject/vmvhzttx.html