LruCache

针对Android应用中大量图片加载导致的内存溢出问题,本文详细介绍了如何利用LRU算法进行有效的图片缓存管理,包括内存缓存和磁盘缓存的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当应用程序UI界面需要显示大量的图片,比如:使用ListView, GridView 或者 ViewPager 这样的组件,随着滑动屏幕图片不断增加,最终会导致OOM,原因如下:

1.Android虚拟机默认为每个App分配16MB的内存空间,不同的真机厂商可以对此值进行设置;
2.Android 系统在加载图片时是解析每一个像素的信息,再把每一个像素全部保存至内存中;
3.一张图片(BitMap)占用的内存=图片长度图片宽度单位像素占用的字节数; 注:图片长度和图片宽度的单位是像素;例如:一张1920x1080的JPG图片,在Android 系统中是以ARGB8888格式储存的,即一个像素需占用4个字节,图片的大小=1920x1080x4=8M。

为了保证内存的使用始终维持在一个合理的范围,通常会把被移除屏幕的图片进行回收处理。此时垃圾回收器也会认为你不再持有这些图片的引用,从而对这些图片进行GC操作。用这种思路来解决问题是非常好的,可是为了能让程序快速运行,在界面上迅速地加载图片,你又必须要考虑到某些图片被回收之后,用户又将它重新滑入屏幕这种情况。这时重新去加载一遍刚刚加载过的图片无疑是性能的瓶颈,你需要想办法去避免这个情况的发生。此时可使用缓存技术解决这个问题,它可以让组件快速地重新加载和处理图片。

目前常用的缓存算法是LRU算法,它的核心思想是优先淘汰那些近期最少使用的缓存对象;采用LRU算法缓存有两种:LruCache(内存缓存)和DiskLruCache(磁盘缓存),其中加载图片时通常是首先从内存缓存中加载,然后是磁盘缓存,最后是网络请求。

如LruCache加载图片时,它会把使用的对象以强引用储存在 LinkedHashMap 中,当储存的缓存值达到我们设置的容量后,会移除最近最少使用的对象,然后再添加新的对象。

private LruCache<String,Bitmap> mMemoryCache;
public MemoryCacheUtils(){
    //获取当前进程的可用内存,单位是KB;
    int maxMemory = (int)(Runtime.getRuntime().maxMemory()/1024);
    //设置缓存的总容量大小为当前进程可用内存的1/8,单位是KB;
    int cacheSize = maxMemory/8;
    mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
       @Override
       //此方法用于计算每张图片的大小,默认返回值是1,这里设置返回该图片的大小单位是KB;
       protected int sizeOf(String key, Bitmap bitmap) {
          return bitmap.getByteCount()/1024;
       }

    };
}


public void addBitmapToMemoryCache(String key,Bitmap bitmap){
   //添加缓存对象
   mMemoryCache.put(key, bitmap);
}


public Bitmap getBitmapFormMemoryCache(String key){
   //获取缓存对象
   return mMemoryCache.get(key);
}


public void remnove(String key){
   //移除特定的缓存对象
   mMemoryCache.remove(key);
}

对于上面的代码设置的容量是当前进程的可用内存的1/8,单位是KB,而sizeOf方法则是计算Bitmap对象的大小,这里将其单位也转化为KB。在一些特殊情况下需要重写LruCache的entryRemove方法,因为LruCache移除缓存时会调用entryRemove方法,因此可在此方法完成一些资源回收工作。当前页面不可以见时,即使前期添加了缓存如调用addBitmapToMemoryCache,后续在返回该页面时仍然需要重新加载缓存,否则获取缓存时将返回null,因此LruCache通常用于在同个页面某些图片需要经常调用的情景中,如Listview,GridView,ViewPager等。

参考:

Android高效加载大图、多图解决方案,有效避免程序OOM
Android中图片的三级缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值