使用三级缓存解决内存溢出
在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;} }}
转载于:https://www.cnblogs.com/huangbei1990/p/5742403.html
使用三级缓存解决内存溢出相关推荐
- 京东一面:Spring 为何需要三级缓存解决循环依赖,而不是二级缓存?我懵了。。...
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:cnblogs.com/semi-sub/p/13548479.html 前言 bean生命周期 三级缓存解决循环依赖 总结 ...
- 为什么Spring需要三级缓存解决循环依赖,而不是二级缓存?
来源:https://www.cnblogs.com/semi-sub/p/13548479.html 在使用spring框架的日常开发中,bean之间的循环依赖太频繁了,spring已经帮我们去解决 ...
- Spring三级缓存解决循环依赖问题详解
spring三级缓存解决循环依赖问题详解 前言 这段时间阅读了spring IOC部分的源码.在学习过程中,自己有遇到过很多很问题,在上网查阅资料的时候,发现很难找到一份比较全面的解答.现在自己刚学习 ...
- Tomcat参数设置,解决内存溢出问题
Tomcat参数设置,解决内存溢出问题 参考文章: (1)Tomcat参数设置,解决内存溢出问题 (2)https://www.cnblogs.com/fan-yuan/p/7213950.html ...
- 循环依赖 三级缓存解决
循环依赖的产生 A对象里面依赖着B对象,B对象依赖着A对象 流程: 当A开始实例化A,然后初始化A,再初始化的A的时候,去实例化B,然后再初始化B,初始化B的时候在去实例化A,产生一个循环依赖. sp ...
- Android使用帧动画解决内存溢出问题
Android使用帧动画解决内存溢出问题 参考文章: (1)Android使用帧动画解决内存溢出问题 (2)https://www.cnblogs.com/mcfawa/p/5192335.html ...
- POI实现大数据EXCLE导入导出,解决内存溢出问题
POI实现大数据EXCLE导入导出,解决内存溢出问题 参考文章: (1)POI实现大数据EXCLE导入导出,解决内存溢出问题 (2)https://www.cnblogs.com/huangjian2 ...
- 原生js.ajax内存溢出,【JS】解决内存溢出问题
首页 专栏 javascript 文章详情 0 解决内存溢出问题 comer发布于 27 分钟前 webpack 运行 npm run build 内存溢出 JavaScript heap out o ...
- html5 image 内存溢出,解决内存溢出问题
webpack 运行 npm run build 内存溢出 JavaScript heap out of memory vue-cli3.0构建的项目,开发过程中,可能会遇到内存溢出的情况,改动一点代 ...
最新文章
- 申卫星:“十四五”数字经济高质量发展需要法治护航
- 深度学习实战_五天入门深度学习,这里有一份PyTorch实战课程
- TextBoxSuggest,输入框提示工具,输入建议,输入匹配,辅助输入,输入即时提示,文本编辑器,Visual Studio效果,高速查询引擎,哈希树,模糊匹配,百万条零毫秒
- make_ext4fs 失败
- 添加用户信息的方法java_添加用户的流程分析
- ASP编程中的Microsoft JScript 编译错误 错误 '800a03ec'缺少;的解决方法.
- Java 语法糖详解
- 【Java入门】桌球小游戏
- 【转】【OPenGL】OPenGL 画图板-- 中点算法画圆
- 语音识别的原理_语音识别原理_语音识别原理框图 - 云+社区 - 腾讯云
- 轻量级网络模型之ShuffleNet
- swagger 上传文件 参数_跟我一起学.NetCore之Swagger让前后端不再烦恼及界面自定义...
- 安卓插件化开发!移动开发程序员怎么优雅迈过30K+这道坎?全网最新
- 逍遥魔兽手动打开mysql_逍遥魔兽gm命令使用
- Qt数据库应用18-横向纵向排版
- win11右键菜单缺少“新建“选项解决办法“
- 招商银行信用卡中心18秋招题解
- python爬取海量精美高清漂酿纯真可爱善良小姐姐壁纸(老司机福利)
- 电子合同的电子签名方法
- Altera特殊管脚的使用(适用全系列Altera FPGA,MSEL区别除外)-来自altera论坛