一丶java.lang.OutOfMemoryError异常常见原因:
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
二丶BitmapFactory.decodeStream出现OutOfMemoryError异常
log:java.lang.OutOfMemoryError: Failed to allocate a 4308492 byte allocation with 467872 free bytes and 456KB until OOM
我以为是我的Bitmap太大了,于是对Bitmap进行一系列优化,点击run,然并卵又TMD出现OutOfMemoryError,还是太年轻啊。
三、解决方法
1.什么是内存泄露?
内存泄露指程序中没有正确的释放用完的内存空间,导致运行异常或错误
2.AndroidStudio如何检测内容泄漏
Tools——Android——Android device monitor
image.png
image.png
image.png
通过AndroidStudio的内存检测工具很清楚的看到内存使用情况,经测试一个几百k的图片,使用BitmapFactory.decodeStream()方法却要试图分配1M的内存
首先我们知道安卓开发中一般从网络获取图像,使用BitmapFactory的decodeStream函数来获取到bitmap。Android又在图像方面面消耗内存较多,本文就主要记录怎样正确的展现图像减少对内存的开销,有效的避免oom现象。那我们的内存为什么会被消耗那么多呢?是因为BitmapFactory的每个decode函数都会生成一个bitmap对象,内存就是去bitmap里了,如果图像过多就会出现OutOfMemoryError异常。不多说,直接上代码,以下为优化方法:
InputStream bitmapIs = HttpUtils.getStreamFromURL(imageURL);
Bitmap bitmap = null;
try {
bitmap =getFitSampleBitmap(bitmapIs);
} catch (Exception e) {
e.printStackTrace();
}
public static Bitmap getFitSampleBitmap(InputStream inputStream) throws Exception{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
byte[] bytes = readStream(inputStream);
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
options.inSampleSize = 2;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
/**
* 从inputStream中获取字节流 数组大小
**/
public static byte[] readStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
outStream.close();
inStream.close();
return outStream.toByteArray();
}
BitmapFactory提供了BitmapFactory.Option,用于设置图像相关的参数, inJustDecodeBounds :如果设置为true则表示decode函数不会生成bitmap对象,仅是将图像相关的参数填充到option对象里,这样我们就可以在不生成bitmap而获取到图像的相关参数了。
inSampleSize:表示对图像像素的缩放比例。假设值为2,表示decode后的图像的像素为原图像的1/2。
在设置了option的inSampleSize后我们将inJustDecodeBounds设置为false再次调用decode函数时就能生成bitmap了。
最后为了保险起见加上如下代码:
if (bitmap.isRecycled()== false ){
bitmap.recycle();
}
如果代码已经不再需要使用Bitmap对象了,手动回收。
网友评论