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个回答

3

在某些情况下(例如循环中的操作),垃圾回收器比您的代码慢。 您可以使用此答案中的辅助方法等待垃圾回收器


3

您需要改变drawable中对象的大小。它对Android来说太大了无法显示。例如,如果您正在设置图像,请尝试使用像素较少的图像。这对我有用。

谢谢 :)

2
Bitmap image =((BitmapDrawable)imageView1.getDrawable()).getBitmap();

ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,50/100,byteArrayOutputStream);

如果使用100,则原始分辨率可能会导致应用程序因内存不足而停止。

如果分辨率为50或低于100,则分辨率将降低到50%或低于100%,从而防止出现内存不足问题。


2
android:hardwareAccelerated="false"设置为特定的活动。希望这样做可以解决冻结和动画问题。像这样...
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true">
.
.
.
.
<activity android:name=".NavigationItemsFolder.GridsMenuActivityClasses.WebsiteActivity"
            android:windowSoftInputMode="adjustPan"
            android:hardwareAccelerated="false"/>
</application>

2

使用像PicassoGlide这样的图像加载库。使用这些库将有助于预防未来的崩溃。


2

我是一个Android开发的新手,但我希望我的解决方案能够帮到你。我正在使用ImageView并将其背景设置为"src",因为我想制作一个帧动画。我遇到了同样的错误,但当我尝试编写代码时,它可以正常工作。

int ImageID = this.Resources.GetIdentifier(questionPlay[index].Image.ToLower(), "anim", PackageName);
            imgView.SetImageResource(ImageID);
            AnimationDrawable animation = (AnimationDrawable)imgView.Drawable;
            animation.Start();
            animation.Dispose();

1
stream = activity.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;

bitmap = BitmapFactory.decodeStream(stream, null, options);
int Height = bitmap.getHeight();
int Width = bitmap.getWidth();
enter code here
int newHeight = 1000;
float scaleFactor = ((float) newHeight) / Height;
float newWidth = Width * scaleFactor;

float scaleWidth = scaleFactor;
float scaleHeight = scaleFactor;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
resizedBitmap= Bitmap.createBitmap(bitmap, 0, 0,Width, Height, matrix, true);
bitmap.recycle();

然后在Application标签中添加largeheapsize="true"。

1

在进入新的活动时,如果没有结束旧的活动,就会遇到这个问题。我通过使用 finish(); 解决了这个问题。

    Intent goToMain = new Intent(this,MainActivity.class);
    startActivity(goToMain);
    finish();

1
如果上传图片,请尝试减少图像质量,这是位图的第二个参数。这是我的解决方案。之前是90,然后我尝试了60(如下面的代码所示)。
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
finalBitmap.compress(Bitmap.CompressFormat.JPEG,60,baos);
byte[] b = baos.toByteArray();

1
尝试最简单的方法。也许您的应用程序崩溃是因为图像大小(以MB为单位)太大,因此没有为其分配空间。因此,在将图像粘贴到drawable之前,请使用任何查看器软件缩小大小,或者如果您在运行时从图库中获取图像,则在保存之前压缩位图。这对我有用。肯定对您有效。

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