使用三级缓存解决内存溢出
来源:互联网 发布:甲骨文软件测试面试 编辑:程序博客网 时间:2024/05/19 21:17
在Android开发的过程中,涉及到图片通常容易产生内存溢出的问题,
使用三级缓存的思路可以比较好的解决这个问题。
如下图所示为三级缓存的示意图,第一级为内存缓存,第二级为软引用缓存,第三级为文件缓存
它们的特点如下图所示。
类图如下图所示,Cache为缓存的接口,定义了缓存必须实现的方法,其他的类均实现了Cache接口。ThreeLevelCache包含有
MemoryCache、SoftReferenceCache和FileCache。
Cache接口
public interface Cache {public void put(String key,Bitmap bitmap);//存入public Bitmap get(String key);//取出public boolean isExist(String key);//是否存在public void clear();//清空}
内存缓存MemoryCache
/** * 内存缓存,设置大小限制,当超过限制,将最近最久未使用的一项移出 * @author huangbei * */public class MemoryCache implements Cache {private Map<String, Bitmap> cache ;private Cache softCache;//内存缓存所占的字节,初始为0private long size ;// 内存缓存当中所占字节的最大限制private long limit ;public MemoryCache(Cache softCache){//设置默认限制为最大运行内存的八分之一setLimit(Runtime.getRuntime().maxMemory() / 8); size=0;this.softCache= softCache;// 放入缓存时是个同步操作 // LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最近使用次数由少到多排列,即LRU // 这样的好处是如果要将缓存中的元素替换,则先遍历出最近最少使用的元素来替换以提高效率 cache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));}public void setLimit(long limit){this.limit=limit;}@Overridepublic void put(String key, Bitmap bitmap) {this.cache.put(key, bitmap);if(!checkSize(bitmap)){remove();}}@Overridepublic Bitmap get(String key) {return cache.get(key);}@Overridepublic boolean isExist(String key) {return cache.containsKey(key);}@Overridepublic void clear() {cache.clear(); }//检查添加的图片是否会超过限制private boolean checkSize(Bitmap bitmap){long bitsize=BitmapUtil.getSizeInBytes(bitmap);if((size+bitsize)<=limit){return true;}else{return false;}}//移除掉超过内存限制的图片private void remove(){Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator(); while (iter.hasNext()) { Entry<String, Bitmap> entry = iter.next(); size -= BitmapUtil.getSizeInBytes(entry.getValue());softCache.put(entry.getKey(), entry.getValue());iter.remove();if (size <= limit) break; }}}
软引用缓存SoftReferenceCache
/** * 软引用缓存,不设置大小限制,内存不够,系统自动释放 * @author huangbei * */public class SoftReferenceCache implements Cache {//软引用缓存private Map<String, SoftReference<Bitmap>> cache;public SoftReferenceCache(){cache = new HashMap<String, SoftReference<Bitmap>>();}@Overridepublic void put(String key, Bitmap bitmap) {cache.put(key, new SoftReference<Bitmap>(bitmap));}@Overridepublic Bitmap get(String key) {return cache.get(key).get();}@Overridepublic boolean isExist(String key) {if(cache.containsKey(key)&&cache.get(key).get()!=null)return true;elsereturn false;}@Overridepublic void clear() {cache.clear(); }}
文件缓存FileCache
/** * 文件缓存,图片存于文件当中,不设置大小限制,避免重复下载,节省流量 * @author huangbei * */public class FileCache implements Cache{ private String cashe_dir=""; private File cacheDir; //图片存储的路径 public FileCache(Context context) { if (android.os.Environment.getExternalStorageState() .equals(android.os.Environment.MEDIA_MOUNTED)){ cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), cashe_dir); }else{ cacheDir = context.getCacheDir(); } if (!cacheDir.exists()) cacheDir.mkdirs(); }@Overridepublic void put(String key, Bitmap bitmap) {File f = new File(cacheDir, key); if(!f.exists()){ try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } BitmapUtil.saveBitmap(f, bitmap);}@Overridepublic Bitmap get(String key) {File f = new File(cacheDir, key); if (f.exists()){ return BitmapUtil.decodeFile(f); }else{ return null; } }@Overridepublic boolean isExist(String key) {File f = new File(cacheDir, key); if (f.exists()){ return true; }else{ return false; } }@Overridepublic void clear() {File[] files = cacheDir.listFiles(); for (File f : files) f.delete();}}
三级缓存 ThreeLevelCache
public class ThreeLevelCache implements Cache{private Cache memoryCache;private Cache softCache;private Cache fileCache;private ThreeLevelCache cache; private ThreeLevelCache(Context context){this.softCache=new SoftReferenceCache();this.fileCache=new FileCache(context);this.memoryCache=new MemoryCache(softCache);}public ThreeLevelCache newInstance(Context context){if(cache==null){ cache=new ThreeLevelCache(context);}return cache;}@Overridepublic void put(String key, Bitmap bitmap) { this.fileCache.put(key, bitmap); this.memoryCache.put(key, bitmap);}@Overridepublic Bitmap get(String key) {if(memoryCache.isExist(key)){return memoryCache.get(key);}else if(softCache.isExist(key)){return softCache.get(key);}else if(fileCache.isExist(key)){return fileCache.get(key);}else{return null;}}@Overridepublic boolean isExist(String key) {return memoryCache.isExist(key)||softCache.isExist(key)||fileCache.isExist(key);}@Overridepublic void clear() {memoryCache.clear();softCache.clear();fileCache.clear();}}
其中所用到的一些关于图片的方法存于类BitmapUtil中
public class BitmapUtil {//图片所占的内存大小public static long getSizeInBytes(Bitmap bitmap) { if (bitmap == null){ return 0; }return bitmap.getRowBytes() * bitmap.getHeight(); }//将图片存入文件当中public static boolean saveBitmap(File file, Bitmap bitmap){ if(file == null || bitmap == null) return false; try { BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); return bitmap.compress(CompressFormat.JPEG, 100, out); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } }// decode这个图片并且按比例缩放以减少内存消耗,虚拟机对每张图片的缓存大小也是有限制的 public static Bitmap decodeFile(File f) { try { // decode image size BitmapFactory.Options option = new BitmapFactory.Options(); option.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f), null, option); // Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE = 100; int width_tmp = option.outWidth, height_tmp = option.outHeight; int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE){ break; } width_tmp /= 2; height_tmp /= 2; scale *= 2; } // decode with inSampleSize BitmapFactory.Options option2 = new BitmapFactory.Options(); option2.inSampleSize = scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, option2); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } }}
0 0
- 使用三级缓存解决内存溢出
- Android--图片加载处理(内存溢出和三级缓存)
- Java导出excel 内存溢出 使用缓存
- 三级缓存的使用
- eclipse使用中内存溢出(缓存)的问题
- tomcat内存溢出解决
- 解决tomcat内存溢出
- 解决MAVEN内存溢出
- Jira 内存溢出解决
- 解决tomcat内存溢出
- 解决tomcat内存溢出
- 解决内存溢出
- 解决MAVEN内存溢出
- 解决内存溢出
- fusioncharts内存溢出解决
- myeclipse 解决内存溢出
- JAVA内存溢出解决
- tomcat内存溢出解决
- 笔试面试13--给定 x, k ,求满足 x + y = x | y 的第 k 小的正整数 y
- XPO开发指南简要
- 线程和进程
- 地理坐标与投影坐标
- drawRect和layoutSubviews的区别
- 使用三级缓存解决内存溢出
- SQL学习笔记1——用代码创建、删除数据库
- C++第六次作业 项目1 项目4
- Android开发常识
- PHP代码优化小笔记
- sharepreferences
- Linux service 创建和注册
- WebStrom 2016.1.1.破解
- centos6.7升级svn1.6到1.8