在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

使用三级缓存解决内存溢出相关推荐

  1. 京东一面:Spring 为何需要三级缓存解决循环依赖,而不是二级缓存?我懵了。。...

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:cnblogs.com/semi-sub/p/13548479.html 前言 bean生命周期 三级缓存解决循环依赖 总结 ...

  2. 为什么Spring需要三级缓存解决循环依赖,而不是二级缓存?

    来源:https://www.cnblogs.com/semi-sub/p/13548479.html 在使用spring框架的日常开发中,bean之间的循环依赖太频繁了,spring已经帮我们去解决 ...

  3. Spring三级缓存解决循环依赖问题详解

    spring三级缓存解决循环依赖问题详解 前言 这段时间阅读了spring IOC部分的源码.在学习过程中,自己有遇到过很多很问题,在上网查阅资料的时候,发现很难找到一份比较全面的解答.现在自己刚学习 ...

  4. Tomcat参数设置,解决内存溢出问题

    Tomcat参数设置,解决内存溢出问题 参考文章: (1)Tomcat参数设置,解决内存溢出问题 (2)https://www.cnblogs.com/fan-yuan/p/7213950.html ...

  5. 循环依赖 三级缓存解决

    循环依赖的产生 A对象里面依赖着B对象,B对象依赖着A对象 流程: 当A开始实例化A,然后初始化A,再初始化的A的时候,去实例化B,然后再初始化B,初始化B的时候在去实例化A,产生一个循环依赖. sp ...

  6. Android使用帧动画解决内存溢出问题

    Android使用帧动画解决内存溢出问题 参考文章: (1)Android使用帧动画解决内存溢出问题 (2)https://www.cnblogs.com/mcfawa/p/5192335.html ...

  7. POI实现大数据EXCLE导入导出,解决内存溢出问题

    POI实现大数据EXCLE导入导出,解决内存溢出问题 参考文章: (1)POI实现大数据EXCLE导入导出,解决内存溢出问题 (2)https://www.cnblogs.com/huangjian2 ...

  8. 原生js.ajax内存溢出,【JS】解决内存溢出问题

    首页 专栏 javascript 文章详情 0 解决内存溢出问题 comer发布于 27 分钟前 webpack 运行 npm run build 内存溢出 JavaScript heap out o ...

  9. html5 image 内存溢出,解决内存溢出问题

    webpack 运行 npm run build 内存溢出 JavaScript heap out of memory vue-cli3.0构建的项目,开发过程中,可能会遇到内存溢出的情况,改动一点代 ...

最新文章

  1. 申卫星:“十四五”数字经济高质量发展需要法治护航
  2. 深度学习实战_五天入门深度学习,这里有一份PyTorch实战课程
  3. TextBoxSuggest,输入框提示工具,输入建议,输入匹配,辅助输入,输入即时提示,文本编辑器,Visual Studio效果,高速查询引擎,哈希树,模糊匹配,百万条零毫秒
  4. make_ext4fs 失败
  5. 添加用户信息的方法java_添加用户的流程分析
  6. ASP编程中的Microsoft JScript 编译错误 错误 '800a03ec'缺少;的解决方法.
  7. Java 语法糖详解
  8. 【Java入门】桌球小游戏
  9. 【转】【OPenGL】OPenGL 画图板-- 中点算法画圆
  10. 语音识别的原理_语音识别原理_语音识别原理框图 - 云+社区 - 腾讯云
  11. 轻量级网络模型之ShuffleNet
  12. swagger 上传文件 参数_跟我一起学.NetCore之Swagger让前后端不再烦恼及界面自定义...
  13. 安卓插件化开发!移动开发程序员怎么优雅迈过30K+这道坎?全网最新
  14. 逍遥魔兽手动打开mysql_逍遥魔兽gm命令使用
  15. Qt数据库应用18-横向纵向排版
  16. win11右键菜单缺少“新建“选项解决办法“
  17. 招商银行信用卡中心18秋招题解
  18. python爬取海量精美高清漂酿纯真可爱善良小姐姐壁纸(老司机福利)
  19. 电子合同的电子签名方法
  20. Altera特殊管脚的使用(适用全系列Altera FPGA,MSEL区别除外)-来自altera论坛

热门文章

  1. 阿里云终端连接与实例管理
  2. Vjudge 2016-5-10 math test
  3. 最小生成树基础 (Kruskal)
  4. HTTP学习笔记1-基本定义
  5. PHP execl导出/展示
  6. asterisk 常用命令
  7. 好用的pdf预览插件
  8. (82)Vivado系统同步接口约束
  9. (27)FPGA译码器设计(第6天)
  10. FPGA资源评估方法