在应用程序的UI界面中加载图片是很常见的事情,但是当程序需要在界面上加载一大堆图片的时候,情况就变得复杂起来。在很多情况下,(比如使用ListView, GridView 或者 ViewPager 这样的组件),屏幕上显示的图片可以通过滑动屏幕等事件不断地增加,最终导致OOM。
为了保证内存的使用始终维持在一个合理的范围,通常需要回收被移除屏幕的图片。此时垃圾回收器也会认为你不再持有这些图片的引用,从而对这些图片进行GC操作。为了能让程序快速运行,在界面上迅速地加载图片,同时考虑到某些图片被回收之后,用户又将它重新滑入屏幕这种情况。这时重新去加载一遍刚刚加载过的图片无疑会造成性能丢失,需要想办法去避免这个情况的发生。因此使用内存缓存技术可以很好的解决这个问题,它可以让组件快速地重新加载和处理图片。内存缓存技术对那些大量占用应用程序宝贵内存的图片提供了快速访问的方法。其中最核心的类是LruCache (此类在android-support-v4的包中提供) 。
LruCache使用一个LinkedHashMap简单的实现内存的缓存,没有软引用,都是强引用。当新添加一个cache或者已有cache再次使用时会将他们放在双向线性列表的头部。如果添加的数据大于设置的最大值,就删除尾部的数据来调整内存。这样就保证了最近使用的被最后删除。这个排序是根据在创建LinkedHashMap时最后一个参数来设置是否有序排列。
下面是一个使用 LruCache 来缓存图片的例子:
private LruCache<String, Bitmap>mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
// LruCache通过构造函数传入缓存值,以KB为单位。
int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
// 使用最大可用内存值的1/8作为缓存的大小。
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap bitmap) {
//重写此方法来衡量每张图片的大小,默认返回图片数量。
return bitmap.getByteCount() / 1024;
}
};
}
public void addBitmapToMemoryCache(String key, Bitmapbitmap) {
if (getBitmapFromMemCache(key) == null){
mMemoryCache.put(key,bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key){
return mMemoryCache.get(key);
}