android的三级缓存,Android图片三级缓存机制

在Android开发中,如果图片过多,而我们又没有对图片进行有效的缓存,就很容易导致OOM(Out Of Memory)错误。因此,图片的缓存是非常重要的,尤其是对图片非常多的应用。现在很多框架都做了很好的图片缓存处理,如Fresco、Glide等。

缓存机制

内存缓存,读取速度最快。

硬盘缓存(文件缓存),读取速度比内存缓存稍慢。

网络缓存,读取速度最慢。

其中内存缓存和硬盘缓存对应的类分别是LruCache和DiskLruCache。Android在Android 3.1加入了LruCache缓存类,其中维护着一个LinkedHashMap。当我们的APP中想要加载某张图片时,先去LruCache中寻找图片,如果LruCache中有,则直接取出来使用,如果LruCache中没有,则去文件系统中寻找,如果有则取出来使用,同时将图片添加到LruCache中,如果没有,则连接网络从网上下载图片。图片下载完成后,将图片通过DiskLruCache缓存到本地,然后放到LruCache中。

实现

public class ImageCache extends LruCache {

private Map> cacheMap;

public ImageCache(Map> cacheMap) {

super((int) (Runtime.getRuntime().maxMemory() / 8));

this.cacheMap = cacheMap;

}

@Override

protected int sizeOf(String key, Bitmap value) {

return value.getRowBytes() * value.getHeight();

}

@Override

protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {

if (oldValue != null) {

SoftReference softReference = new SoftReference(oldValue);

cacheMap.put(key, softReference);

}

}

public Map> getCacheMap() {

return cacheMap;

}

}

ImageCache继承自LruCache,当图片被LruCache移除的时候,我们需要手动将这张图片添加到软引用(SoftReference)中。我们需要在项目中维护一个由SoftReference组成的集合,其中存储被LruCache移除出来的图片。软引用的一个好处是当系统空间紧张的时候,软引用可以随时销毁,因此软引用是不会影响系统运行的。

工具类

public class CacheUtil {

private static CacheUtil instance;

private Context context;

private ImageCache imageCache;

private CacheUtil(Context context) {

this.context = context;

Map> cacheMap = new HashMap<>();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { // SDK版本判断

this.imageCache = new ImageCache(cacheMap);

}

}

public static CacheUtil getInstance(Context context) {

if (instance == null) {

synchronized (CacheUtil.class) {

if (instance == null) {

instance = new CacheUtil(context);

}

}

}

return instance;

}

/**

* 将图片添加到缓存中

*/

private void putBitmapIntoCache(String fileName, byte[] data) {

// 将图片的字节数组写入到内存中

FileUtil.getInstance(context).writeFileToStorage(fileName, data);

// 将图片存入强引用(LruCache)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {

imageCache.put(fileName, BitmapFactory.decodeByteArray(data, 0, data.length));

}

}

/**

* 从缓存中取出图片

*/

private Bitmap getBitmapFromCache(String fileName) {

// 从强引用(LruCache)中取出图片

Bitmap bm = null;

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { // SDK版本判断

bm = imageCache.get(fileName);

if (bm == null) {

// 如果图片不存在强引用中,则去软引用(SoftReference)中查找

Map> cacheMap = imageCache.getCacheMap();

SoftReference softReference = cacheMap.get(fileName);

if (softReference != null) {

bm = softReference.get();

imageCache.put(fileName, bm);

} else {

// 如果图片不存在软引用中,则去内存中找

byte[] data = FileUtil.getInstance(context).readBytesFromStorage(fileName);

if (data != null && data.length > 0) {

bm = BitmapFactory.decodeByteArray(data, 0, data.length);

imageCache.put(fileName, bm);

}

}

}

}

return bm;

}

/**

* 使用三级缓存为ImageView设置图片

*/

public void setImageToView(final String path, final ImageView view) {

final String fileName = path.substring(path.lastIndexOf(File.separator) + 1);

Bitmap bm = getBitmapFromCache(fileName);

if (bm != null) {

view.setImageBitmap(bm);

} else {

// 从网络获取图片

new Thread(new Runnable() {

@Override

public void run() {

byte[] b = HttpUtil.getInstance().getByteArrayFromWeb(path);

if (b != null && b.length > 0) {

// 将图片字节数组写入到缓存中

putBitmapIntoCache(fileName, b);

final Bitmap bm = BitmapFactory.decodeByteArray(b, 0, b.length);

// 将从网络获取到的图片设置给ImageView

view.post(new Runnable() {

@Override

public void run() {

view.setImageBitmap(bm);

}

});

}

}

}).start();

}

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值