我想显示的位图图像在ImageView从sd卡已经存储。运行后,我的应用程序是崩溃和得到OutOfMemoryError错误:

(. lang。OutOfMemoryError:未能分配23970828字节分配,2097152空闲字节和2MB直到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)

当前回答

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

其他回答

这对我来说很有效:只需要将图像从可绘制文件夹移动到可绘制的hdpi。

我得到了下面的错误

"E/art: throws OutOfMemoryError "分配47251468字节失败 分配16777120个空闲字节和23MB直到OOM"

在AndroidManifest.xml中添加android:largeHeap="true"后,我消除了所有错误

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

你试过把这个加到你的申请清单里吗?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" >

I have found that images in the 'drawable' folder will get converted to a much larger image on high def phones. For example, a 200k image will be resampled to a higher res, like 800k or 32000k. I had to discover this on my own and to date have not seen documentation for this heap memory trap. To prevent this I put everything in a drawable-nodpi folder (in addition to using 'options' in BitmapFactory based on the particular device heap). I can't afford to have the size of my app bloated with multiple drawable folders, particularly as the range of screen defs is so vast now. The tricky thing is studio now doesn't specifically indicate the 'drawable-nodpi' folder as such in the project view, it just shows a 'drawable' folder. If you're not careful, when you drop an image to this folder in studio, it won't actually get dropped into the drawable-nodpi:

Careful here 'backgroundtest' did not actually go to drawable-nodpi and will 
be resampled higher, such as 4x or 16x of the original dimensions for high def screens.

一定要单击对话框中的nodpi文件夹,因为项目视图不会像以前那样分别显示所有可绘制的文件夹,所以不会立即显示到错误的文件夹。在我很久以前删除了它之后,Studio在某个时候为我重新创建了香草“可绘制”:

我真的不建议像这样编辑清单

android:hardwareAccelerated=“错误”,android:largeHeap=“真实”

这些选项会导致应用程序的动画效果不流畅。此外,“liveData”或更改本地DB(Sqlite, Room)激活缓慢。这不利于用户体验。

所以我推荐RESIZE位图

下面是示例代码

fun resizeBitmap(source: Bitmap): Bitmap {
      val maxResolution = 1000    //edit 'maxResolution' to fit your need
      val width = source.width
      val height = source.height
      var newWidth = width
      var newHeight = height
      val rate: Float

            if (width > height) {
                if (maxResolution < width) {
                    rate = maxResolution / width.toFloat()
                    newHeight = (height * rate).toInt()
                    newWidth = maxResolution
                }
            } else {
                if (maxResolution < height) {
                    rate = maxResolution / height.toFloat()
                    newWidth = (width * rate).toInt()
                    newHeight = maxResolution
                }
            }
            return Bitmap.createScaledBitmap(source, newWidth, newHeight, true)
 }