简述图片加载框架

来源:互联网 发布:android源码网 编辑:程序博客网 时间:2024/04/19 10:13

南海争端在即,台海问题未解决,国家尚未统一,哪有心思写代码,即使吃着地沟油命,也不能隐藏一颗中南海的心,我们中国连红绿灯都不让,居然叫我们让中国的南海,真搞笑。。。

今天无心写代码,在公司就是看看新闻和整理点知识点了,无意间翻到我之前画给朋友的一张图,关于三级缓存和一些名词的解释,不多说,不怂,就是干,如下:

三级缓存

此处采用的是“内存–文件–网络”三级缓存,之前看过xutils 和imageloader 源码,图片加载这块都是采用这种方式,现在Picasso 和glide 也是采用这个模式,只是内部一些细节处理和优化不一样而已,fresco 源码没看过,没法做出评论,对于网络会否属于cache,这个不做讨论,总的来说,现在统称三级缓存。通过此图,简单说下加载过程,如下:

首先先去判断内存中获取图片,如果返回的bitmap 不为null,则抓取此bitmap 显示,如果返回到的bitmap 为null,则去SD卡的文件中查找,如果能查找到则显示此bitmap,如果此时的bitmap 还是null,则去网络下载,下载后的图片通过LruChche 缓存到一级缓存中,即内存中,以下载链接的url通过base64 加密后的名称做为文件名,生成一个.0的文件,此步骤可以通过文件管理器验证,找到缓存的路径,通过图片查看工具查看,此名称也是去一级缓存获取图片的依据,url 通过base64 加密后做为key去LruCache 中获取,还有SD卡文件中获取的依据。

通过上述的叙述,可能会有这样的疑问,为什么加密后的文件后缀是.0,这个主要是从文件的安全性考虑,如果是 png 或者 JPEG 格式,图片扫描器会直接扫描到,图片就会直接暴露出来。

对于三级缓存,早期的加载框架比如afinal,内存缓存采用的是强引用缓存和软引用缓存两部分,二级缓存后来有衍生出DiskLruCache ,三级缓存始终如一,一直未变过。

现在解释下上述的两个名词还有扩展的两个名词:

强引用缓存:指的是就算app发生OOM也不会释放内存,对于图片加载框架,一般都是采用LinkedHashMap,主要原因是因为LinkedHashMap支持LruCache,并能设置长度大小和内存大小,同时也能设置排序类型(插入排序或者访问排序),但是LinkedHashMap却不支持同步,只能通过synchronized 方式达到安全访问的目的。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

/** * created by zero on 2016-07-14 *  * 图片加载测试类 */public class ZeroImageLoader{    // 最大长度    private static final int MAX_CAPACITY = 0X000014;    /**     * initialCapacity:最大容量     *      * loadFactor:加载因子,用于排序算法 ,赋值一般是 0.75f     *      * accessOrder:true为插入排序,false为访问排序(get一个元素后,这个元素被加到最后,使用了LRU 最近最少被使用的调度算法)     *      */    Map<String, Bitmap> strongReferenceCache = new LinkedHashMap<String, Bitmap>(            MAX_CAPACITY, 0.75f, true)    {        private static final long serialVersionUID = 1L;        /**         * 根据返回值,移除LinkedHashMap中最老的键和值         */        protected boolean removeEldestEntry(Map.Entry<String, Bitmap> eldest) {            if (this.size() > MAX_CAPACITY)            {                // 加入软引用缓存                softReferenceCache.put(eldest.getKey(),                        new SoftReference<Bitmap>(eldest.getValue()));                // 加入本地缓存                return true;            }            return false;        };    };    Map<String, SoftReference<Bitmap>> softReferenceCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>();    //此处只做简单演示    Map<String, WeakReference<Bitmap>> weakReferenceCache = new ConcurrentHashMap<String, WeakReference<Bitmap>>();}

软引用缓存:指的是内存不足的时候,当垃圾回收器扫描到该缓存的时候,就会被垃圾回收器回收,主要是用来描述一些有用但并不是必需的对象,可以很好地解决OOM情况。

Map<String, SoftReference<Bitmap>> softReferenceCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>();

弱引用缓存:指的是当垃圾回收器扫描到此处垃圾,无论内存是否充足,都会回收,功能上和软引用如出一辙。对于弱引用,可以很好的做一个测试,如下:

/** *  * created by zero on 2016-07-13 *  * 测试弱引用 * */public class TestWeak{    public static void main(String[] args) {        WeakReference<String> name = new WeakReference<String>(new String("zero"));        System.out.println(name.get());        System.gc();        System.out.println(name.get());    }}结果:zeronull

第二个打印为null,说明此处的虚引用缓存已经被回收。

虚引用缓存:只是一个虚拟出来的内存,跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。所以看到还有很多相关文章还在推荐用软引用或弱引用 (SoftReference or WeakReference),就有点out了。

对于以上四种引用,此片不做太多叙述,涉及到的内容太多,还有完整图片缓存框架,日后都会单独写一篇贴子,包括本地文件缓存,现在流行的DiskLruCache,本篇也就不作讲解。本篇主要目的就是简单了解图片加载框架中有哪些内容,走的是一个什么样的过程,四种引用的基本概念。

6 2
原创粉丝点击