Android BitmapFactory.decodeStream方法OutOfMemoryError 解决方法

我的Android App在执行下面代码时出现了OutOfMemoryError异常

image = BitmapFactory.decodeStream(assetManager.open(imgFilename));

App执行到这一步就会出现OOM异常,异常信息如下:

(...)
08-05 21:22:12.443: I/dalvikvm-heap(2319): Clamp target GC heap from 25.056MB to 24.000MB
08-05 21:22:12.443: D/dalvikvm(2319): GC_FOR_MALLOC freed <1K, 50% free 2709K/5379K, external 18296K/19336K, paused 58ms
08-05 21:22:14.513: D/dalvikvm(2319): GC_EXTERNAL_ALLOC freed <1K, 50% free 2709K/5379K, external 18296K/19336K, paused 101ms
08-05 21:22:14.903: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB
08-05 21:22:14.903: D/dalvikvm(2319): GC_FOR_MALLOC freed 0K, 50% free 2709K/5379K, external 18312K/19336K, paused 53ms
08-05 21:22:22.843: D/ddm-heap(2319): Heap GC request
08-05 21:22:22.963: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB
08-05 21:22:22.963: D/dalvikvm(2319): threadid=1: still suspended after undo (sc=1 dc=1)
08-05 21:22:22.963: D/dalvikvm(2319): GC_EXPLICIT freed 1K, 50% free 2710K/5379K, external 18312K/19336K, paused 116ms

通过DDMS可以看到当时内存堆的使用情况

  • Heap Size:  5.254 MB
  • Allocated:  2.647 MB
  • Free:   2.607 MB
  • %Used:  50.38%
  • #Objects    49,028

  

只要指定到这一行就会出现OutOfMemoryError异常

08-05 21:26:04.783: D/dalvikvm(2319): GC_EXTERNAL_ALLOC freed <1K, 50% free 2710K/5379K, external 18312K/19336K, paused 57ms
08-05 21:26:05.023: E/dalvikvm-heap(2319): 2097152-byte external allocation too large for this process.
08-05 21:26:05.163: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB
08-05 21:26:05.163: E/GraphicsJNI(2319): VM won't let us allocate 2097152 bytes
08-05 21:26:05.163: D/dalvikvm(2319): GC_FOR_MALLOC freed 0K, 50% free 2710K/5379K, external 18312K/19336K, paused 30ms
08-05 21:26:05.283: D/skia(2319): --- decoder->decode returned false

在windows中可以看到图片文件的大小是小于400K的,而BitmapFactory.decodeStream()方法却要试图分配2M的内存。

出现这个异常是因为Android类库在处理图片载入时不是很智能,我们还需要做一些额外的工作。

我测试发现,Drawable.createFromStream方法要比BitmapFactory.decodeStream方法占用更多的内存。

你可以通过修改图片的颜色模式(Color schema)来减少创建图片使用的内存量

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);

这个可以参考: http://developer.android.com/reference/android/graphics/Bitmap.Config.html

你也可以通过加载一个缩放之后的图片,来减少创建图片时的内存分配量,但是需要注意图片缩放后可能会损失质量

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);

可以参考: http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html 要动态设置图片的inSampleSize,需要先得到图片的尺寸。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeStream(stream, null, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
options.inJustDecodeBounds = false;
// recreate the stream
// make some calculation to define inSampleSize
options.inSampleSize = ?;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);

你可以根据用户手机屏幕的大小来计算图片的尺寸,如下代码可以获得手机设备的尺寸。

DisplayMetrics metrics = new DisplayMetrics();
((Activity) activity).getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight =metrics.heightPixels;
上一篇:java OutOfMemoryError异常  下一篇:tomcat 报错 java.lang.OutOfMemoryError ( PermGen space)异常的解决方法
推荐阅读:
  • java语言从入门到精通——分支语句 08
  • java语言从入门到精通——为什么用抽象类 24
  • java语言从入门到精通——类集框架(一) 41
  • java语言从入门到精通——练习课(二) 09
  • java语言从入门到精通——包和访问权限(一) 25
  • java语言从入门到精通——类集框架(二) 42
  • java语言从入门到精通——循环语句 10
  • java语言从入门到精通——包和访问权限(二) 26
  • java语言从入门到精通——类集框架(三) 43
  • Android内存泄漏研究
  • requestAnimationFrame最佳实践

你可能感兴趣的:(Bitmap)