Android图片的三级缓存管理

Android的很多应用程序都有多图片的浏览功能,而图片多了很容易造成OOM,而且处理不好用户体验会很差,本文应用了一个硬缓存-软缓存-硬盘缓存的图片加载机制,来加快图片加载的速度和避免出现OOM。
一、设计分析:
1、硬缓存,在内存中级别最高,不会被GC回收的部分,使用LruCache;软存使用SoftReference,在内存中级别低于硬缓存,在内存紧张的时候会被GC回收;硬盘缓存使用DiskLruCache。对于lrucache与DiskLruCache不熟悉的,可参考http://blog.csdn.net/guolin_blog/article/details/34093441
2、实现原理,最近使用的图片存入LruCache中,在LruChche中被清除的图片放入软存,而全部图片都在硬盘中缓存一份。当需要加载图片时,先搜索LruCache,有直接返回,没有继续搜索SoftReference,如果有,先将图片取出在SoftReference中删除,存入LruCache并返回,没有继续搜索DiskLruCache,如果没有就开启任务去网络下载。下载完成后在LruCache中缓存一份,在DiskLruCache中缓存一份。
二、代码分析:
1、LruCache的初始化与设置

int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 8; // 硬引用缓存容量,为系统分配内存的1/8
mLruCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                if (value != null)
                    return value.getRowBytes() * value.getHeight();
                else
                    return 0;
            }

            @Override
            protected void entryRemoved(boolean evicted, String key,
                    Bitmap oldValue, Bitmap newValue) {
                if (oldValue != null)
                    // 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存
                    mSoftCache.put(key, new SoftReference<Bitmap>(oldValue));
            }
        };

LruCache的可缓存大小设置为本机为本应用开辟的最大内存的1/8,实现entryRemoved方法,在这里面将要被移除的图片加入软存中。
2、软存设置
软存使用LinkedHashMap配合SoftReference的形式

private LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache;
private final int SOFT_CACHE_SIZE = 15;
mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(
                SOFT_CACHE_SIZE, 0.75f, true) {

            private static final long serialVersionUID = 1L;

            @Override
            protected boolean removeEldestEntry(
                    Entry<String, SoftReference<Bitmap>> eldest) {
                if (size() > SOFT_CACHE_SIZE) {
                    return true;
                }
                return false;
            }
        };

这里设置软存的最大存储量是15个,重写removeEldestEntry方法,当图片数量多于15个时,销毁最早进入的图片。
3、硬盘缓存直接使用比较成熟稳定的DiskLruCache


/**
     * 硬盘缓存版本
     */
    private final int DISKLRU_VERSON = 1;
    /**
     * 硬盘缓存大小
     */
    private final int DISKLRU_SIZE = 10 * 1024 * 1024;
    /**
     * 硬盘缓存文件名称
     */
    private final String DISKLRU_NAME = "imagecache";
    private DiskLruCache mDiskLruCache;
try {
            // 获取图片缓存路径
            File cacheDir = getDiskCacheDir(context, DISKLRU_NAME);
            if (!cacheDir.exists()) {
                cacheDir.mkdirs();
            }
            // 创建DiskLruCache实例,初始化缓存数据
            mDiskLruCache = DiskLruCache.open(cacheDir,
                    Utils.getAppVersion(context), DISKLRU_VERSON, DISKLRU_SIZE);
        } catch (IOException e) {
            e.printStackTrace();
        }

DiskLruCache不熟悉的可以参考
http://blog.csdn.net/guolin_blog/article/details/28863651
4、如果以上三步没有拿到bitmap,那么就要去网络下载了,本文使用AsyncTask下载。并使用set和List模仿一个简单的线程池,控制图片下载的并发数。具体代码参见:
http://download.csdn.net/detail/suyiyang888/9095027
水平有限,仅供参考。
感谢:
http://my.csdn.net/sinyu890807

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值