zoukankan      html  css  js  c++  java
  • 内存溢出的解决方案


          最近做新闻客户端的时候在加载ListView的大图时会发生内存溢出的问题。内存溢出(OOM)。为了便于理解,我们不妨打个比方。缓冲区溢出好比是将十磅的糖放进一个只能装五磅的容器里。一旦该容器放满了,余下的部分就溢出在柜台和地板上,弄得一团糟。由于计算机程序的编写者写了一些编码,但是这些编码没有对目的区域或缓冲区——五磅的容器——做适当的检查,看它们是否够大,能否完全装入新的内容——十磅的糖,结果可能造成缓冲区溢出的产生。如果打算被放进新地方的数据不适合,溢得到处都是,该数据也会制造很多麻烦。但是,如果缓冲区仅仅溢出,这只是一个问题。到此时为止,它还没有破坏性。当糖溢出时,柜台被盖住。可以把糖擦掉或用吸尘器吸走,还柜台本来面貌。与之相对的是,当缓冲区溢出时,过剩的信息覆盖的是计算机内存中以前的内容。除非这些被覆盖的内容被保存或能够恢复,否则就会永远丢失。

           首先想到的是三级缓存,从服务器下载下来的图片经过网络缓存,但是这种方法不优先加载, 速度慢,浪费流量。然后是本地缓存,次优先加载, 速度快;最后最好的是内存缓存,优先加载, 速度最快。我们都知道Android默认给每个app只分配16M的内存,所以用软引用 SoftReference   在内存不够时,垃圾回收器会考虑回收。但是在安卓2.3+,系统会优先将SoftReference的对象提前回收掉, 即使内存够用。所以谷歌官方建议用LruCache。least recentlly use 最少最近使用算法

    会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定。其实LruCache就是用了很多的HashMap,三百多行的代码。


    /**
     * 内存缓存 
     */
    public class MemoryCacheUtils {
    
    	// private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
    	// HashMap<String, SoftReference<Bitmap>>();
    	private LruCache<String, Bitmap> mMemoryCache;
    
    	public MemoryCacheUtils() {
    		long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模拟器默认是16M
    		mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
    			@Override
    			protected int sizeOf(String key, Bitmap value) {
    				int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
    				return byteCount;
    			}
    		};
    	}
    
    	/**
    	 * 从内存读
    	 * 
    	 * @param url
    	 */
    	public Bitmap getBitmapFromMemory(String url) {
    		// SoftReference<Bitmap> softReference = mMemoryCache.get(url);
    		// if (softReference != null) {
    		// Bitmap bitmap = softReference.get();
    		// return bitmap;
    		// }
    		return mMemoryCache.get(url);
    	}
    
    	/**
    	 * 写内存
    	 * 
    	 * @param url
    	 * @param bitmap
    	 */
    	public void setBitmapToMemory(String url, Bitmap bitmap) {
    		// SoftReference<Bitmap> softReference = new
    		// SoftReference<Bitmap>(bitmap);
    		// mMemoryCache.put(url, softReference);
    		mMemoryCache.put(url, bitmap);
    	}
    }
    java中的引用
    
    - 强引用 垃圾回收器不会回收, java默认引用都是强引用
    - 软引用 SoftReference   在内存不够时,垃圾回收器会考虑回收
    - 弱引用 WeakReference  在内存不够时,垃圾回收器会优先回收
    - 虚引用 PhantomReference  在内存不够时,垃圾回收器最优先回收
    
    
    </pre><pre name="code" class="java">为进一步优化,我们还可以考虑图片压缩技术:

    //图片压缩处理
    				BitmapFactory.Options option = new BitmapFactory.Options();
    				option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
    				option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式


    当然,如果我们用BitmapUtils也是可以的。


  • 相关阅读:
    Redis 设计与实现 2:Redis 对象 redisObject
    Redis 设计与实现 1:数据库 redisDb
    KafkaProducer 简析
    G1 收集器
    KafkaMirrorMaker 的不足以及一些改进
    Redis 数据结构与对象编码 (Object Encoding)
    跨境 TCP 传输优化实录 — 使用 BBR 解决 LFN 问题
    TCP 协议简析
    使用模拟退火算法优化 Hash 函数
    LSM-Tree 与 B-Tree
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314916.html
Copyright © 2011-2022 走看看