简述图片加载框架

标签: 三级缓存图片加载四种引用
1716人阅读 评论(0) 收藏 举报
分类:

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

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

三级缓存

此处采用的是“内存–文件–网络”三级缓存,之前看过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());
    }
}

结果:
zero
null

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

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

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

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

7
2

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:217148次
    • 积分:2662
    • 等级:
    • 排名:第14622名
    • 原创:44篇
    • 转载:0篇
    • 译文:0篇
    • 评论:304条
    QQ交流群

    Android路上

    611566797
    博客专栏
    我的公众号