内存溢出的解决方案


      最近做新闻客户端的时候在加载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也是可以的。


posted @ 2015-11-29 16:45  朱培  阅读(294)  评论(0编辑  收藏  举报