Android:java.lang.OutOfMemoryError:无法分配23970828字节的内存,还剩2097152字节和2MB的可用空间,直到OOM。

434

我想从SD卡中显示已存储的Bitmap图像在ImageView中。运行我的应用程序后出现了错误并收到OutOfMemoryError错误消息:

(java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM)

我不知道为什么会出现内存不足的问题。我认为我的图像大小很大,所以尝试了一些修改。

Iterator<String> it = imageArray.iterator();
while (it.hasNext()) {
  Object element = it.next();
  String objElement = element.toString();
  Log.e("objElement ", " = " + objElement);
  final ImageView imageView = new ImageView (getContext());
  final ProgressBar pBar = new ProgressBar(getContext(), null, 
                                           android.R.attr.progressBarStyleSmall);
  imageView.setTag(it);
  pBar.setTag(it);

  imageView.setImageResource(R.drawable.img_placeholder);
  pBar.setVisibility(View.VISIBLE);

  if (objElement.endsWith(mp3_Pattern)) {
     Log.e("Mp3 ", " ends with ");
     pBar.setVisibility(View.GONE);
     imageView.setImageResource(R.drawable.audio_control);
  }
  if (objElement.endsWith(png_Pattern)) {
     Bitmap bitmap = BitmapFactory.decodeFile(objElement);
     int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
     int x = (bitmap.getWidth() - size) / 2;
     int y = (bitmap.getHeight() - size) / 2;
     Bitmap bitmap_Resul = Bitmap.createBitmap(bitmap, x, y, size, size);
     Log.e("bitmap_Resul "," = "+ bitmap_Resul);

     if (bitmap_Resul != bitmap) {
        bitmap.recycle();
     }
     imageView.setImageBitmap(bitmap_Resul);
     Log.e("png_Pattern ", " ends with ");
     Log.e(" bitmap "," = " + bitmap);
  }

  holder.linearLayout.addView(imageView);
  holder.linearLayout.addView(pBar);

日志信息:

08-27 14:11:15.307    1857-1857/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.tazeen.classnkk, PID: 1857
    java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM
            at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
            at android.graphics.Bitmap.nativeCreate(Native Method)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:709)
            at android.graphics.Bitmap.createBitmap(Bitmap.java:634)
            at com.example.tazeen.classnkk.AllPosts_Page$MyListAdapter.getView(AllPosts_Page.java:357)
            at android.widget.AbsListView.obtainView(AbsListView.java:2347)
            at android.widget.ListView.makeAndAddView(ListView.java:1864)
            at android.widget.ListView.fillDown(ListView.java:698)
            at android.widget.ListView.fillFromTop(ListView.java:759)
            at android.widget.ListView.layoutChildren(ListView.java:1659)
            at android.widget.AbsListView.onLayout(AbsListView.java:2151)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
            at android.view.View.layout(View.java:15671)
            at android.view.ViewGroup.layout(ViewGroup.java:5038)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

7
检查图像的像素,宽度不能超过1440,高度不能超过2560。这样做可以避免出现OutOfMemoryError错误。 - Pankaj Lilan
4
你在哪里找到这些数值(1440 X 2560)?有没有参考Android文档? - LCJ
请参见 https://dev59.com/puo6XIcBkEYKwwoYTzNK。 - JFreeman
1
@PankajLilan 你能分享一下参考资料吗? - Arnab Mukherjee
@LCJ 你找到这背后的参考或逻辑了吗? - Arnab Mukherjee
@ArnabMukherjee 不。 - LCJ
32个回答

654

OutOfMemoryError是在处理位图时在Android中最常见的问题。当对象无法分配内存空间且垃圾回收器无法释放一些空间时,Java虚拟机(JVM)会抛出此错误。

如Aleksey所述,您可以在清单文件中添加以下实体android:hardwareAccelerated="false"android:largeHeap="true",这对某些环境有效。

<application
    android:allowBackup="true"
    android:hardwareAccelerated="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

你应该一定要阅读Android开发者概念的一些内容,特别是这里:高效显示位图

阅读所有五个主题并重新编写你的代码。如果仍然无法解决问题,我们将很乐意查看你在教程材料中做错了什么。

以下是这种类型错误的一些可能答案:

Android:BitmapFactory.decodeStream()在有2MB可用堆空间的情况下使用400KB文件时出现内存不足

如何解决Android中的java.lang.OutOfMemoryError错误

Android:java.lang.OutOfMemoryError

java.lang.OutOfMemoryError

OutOfMemoryError解决方案:位图大小超过VM预算

编辑:来自@cjnash的评论

对于任何仍然在添加此行后崩溃的人,请尝试将您的图像放入res/drawable-xhdpi/文件夹而不是res/drawable/,这应该解决此问题。


11
添加了这个之后,应用程序导航变得非常缓慢。 - Uma Achanta
15
android:hardwareAccelerated="false" 会导致您的应用程序冻结。 - Rahim Rahimov
5
如果您添加了此行代码后仍然遇到崩溃问题,请尝试将图像放入res/drawable-xhdpi/文件夹中,而不是res/drawable/文件夹中,这可能会解决您的问题。 - cjnash
10
为什么你建议将 android:hardwareAccelerated="false"?它有什么好处?为了解决可能出现的应用程序兼容性问题,您可以将 android:hardwareAccelerated 属性设置为 false。这将禁用硬件加速功能,以便应用程序可以在不支持硬件加速的设备上运行。但是,这样会导致应用程序性能下降,因为它将使用软件渲染而不是 GPU 加速。 - Emil
9
将**android:hardwareAccelerated="false"**设置为假,会停止我的应用程序中许多动画,比如阴影和高度。 - Nilesh Rathore
显示剩余11条评论

103

你尝试将这个添加到应用程序清单(manifest)中了吗?android:largeHeap="true"

像这样

  <application
      android:name=".ParaseApplication"
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme"
      android:largeHeap="true" >

21
我尝试了使用android:largeHeap="true",但是仍然得到相同的错误。 - androidTag
1
在使用此链接之前,请尝试压缩您的图像,可以使用 https://tinyjpg.com/ 进行压缩。 - TSG
1
你可以使用这个网站来压缩PNG图片。 - TSG

43

我的问题在于,我的.png文件被解压缩后在内存中成为了一个非常巨大的位图,因为这张图片有非常大的尺寸(即使文件大小很小)。

所以解决方法就是简单地调整图片大小:)


5
这是正确的解决方案,因为我先尝试了其他解决方案,但在应用“android:hardwareAccelerated =“false””后,一些动画效果如布局阴影没有作用。但是,重新调整大小后所有问题都得到解决,谢谢!这个提示给你加1分! - Kaushal28
1
这解决了我的问题。谢谢@petrus - Hùng Nguyễn
这对我也起作用了!好的解决方案!谢谢。 - Razvan22

33

实际上,您可以在清单中添加以下行:android:hardwareAccelerated="false"android:largeHeap="true",对于某些情况有效,但请注意,代码的其他部分可能会与此产生争议。

<application
    android:allowBackup="true"
    android:hardwareAccelerated="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

2
使用Bitmap.createBitmap时出现相同错误导致程序崩溃。 - Narendra Singh
@King 对不起(我也花了一些时间解决这个问题,它对我有用。但这只是其中的一种方法......有很多不同的方法) - Sirop4ik
2
android:hardwareAccelerated="false" 的目的是什么? - IgorGanapolsky
@IgorGanapolsky 从官方文档中得知... 请参见此链接 - Shailendra Madda

29

这应该可以运行

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inSampleSize = 8;

 mBitmapSampled = BitmapFactory.decodeFile(mCurrentPhotoPath,options);

13

调整图片大小后再像这样设置到ImageView中:

Bitmap.createScaledBitmap(_yourImageBitmap, _size, _size, false);

其中size是ImageView的实际大小。您可以通过测量来获取大小:

imageView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

并使用下一个尺寸imageView.getMeasuredWidth()imageView.getMeasuredHeight()来进行scaling


我已经尝试使用android:largeHeap="true",但仍然出现相同的错误。 - androidTag
这里有一个进一步的例子,说明为什么这并不一定可行(使用私有应用程序存储):将位图放置在res/drawable/中可能会出现相同的错误,但并非每次都会发生。将相同的位图放置在res/drawable-xhdpi/中将不再出现该错误。因此,作为答案,它本身并不正确。 - CmosBattery

11

我添加了android:largeHeap="true"AndroidManifest.xml后,成功解决以下错误:

"E/art: Throwing OutOfMemoryError "Failed to allocate a 47251468 byte allocation with 16777120 free bytes and 23MB until OOM"

<application
    android:allowBackup="true"
    android:icon="@mipmap/guruji"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:largeHeap="true"
    android:theme="@style/AppTheme">

10

使用 Glide Library 并覆盖大小为更小的大小;

Glide.with(mContext).load(imgID).asBitmap().override(1080, 600).into(mImageView);

7
问题:无法分配37748748字节的内存,只有16777120个空闲字节和17MB,直到OOM
解决方案: 1.打开你的清单文件 2.在应用程序标签中添加以下两行
 android:hardwareAccelerated="false"
 android:largeHeap="true"

例子:

 <application
        android:allowBackup="true"
        android:hardwareAccelerated="false"
        android:largeHeap="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

7

我已经通过将图片大小调整为较低的尺寸来解决了这个问题。我正在使用Xamarin表格。减小PNG图像的大小解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接