Android 可绘制文件夹内存不足错误

Android Out of Memory error on drawable folder

在我的 android 应用程序中,将所有图像都放在可绘制文件夹中。在大多数手机上,我们没有遇到任何问题。但是有些手机有内存不足的错误。例如,当图像复制到 drawable-xhdpi 文件夹时,问题就消失了。这个问题是什么原因,我该如何解决?

不同的设备可能有不同的大小限制。尝试使用:drawable-xxhdpi

有用的秘籍sheet:http://i.stack.imgur.com/kV4Oh.png

drawable 等同于 drawable-mdpi

如果您将图像放在该文件夹中,它们将针对更高分辨率的设备进行上采样,如果图像较大,则上采样可能会触发 OOM。

如果您在 drawable-xhdpi 中放置相同大小的图像,您将仅在较大的 xxhdpi 设备上获得升采样图像,而在其他设备上降采样图像。

如果您想避免自动 up/down 图像采样,请将它们放在 drawable-nodpi 文件夹中。

为了管理 Out Of Memory Error 您可能需要做的一件事是通过压缩图像来减小图像大小并将其保持在可绘制状态 folders.which 对于减小应用程序大小和运行时的内存消耗很有用.

或者您可能需要使用以下 class 来减小图像尺寸的纵横比。

ImageResizer

  public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                         int reqWidth, int reqHeight, boolean isLow) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        if (isLow) {
            options.inPreferredConfig = Bitmap.Config.RGB_565;
        }
        BitmapFactory.decodeResource(res, resId, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }


    /**
     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
     * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
     * the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap
     * having a width and height equal to or larger than the requested width and height.
     *
     * @param options   An options object with out* params already populated (run through a decode*
     *                  method with inJustDecodeBounds==true
     * @param reqWidth  The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return The value to be used for inSampleSize
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth, int reqHeight) {
        // BEGIN_INCLUDE (calculate_sample_size)
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger inSampleSize).

            long totalPixels = width * height / inSampleSize;

            // Anything more than 2x the requested pixels we'll sample down further
            final long totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels > totalReqPixelsCap) {
                inSampleSize *= 2;
                totalPixels /= 2;
            }
        }
        return inSampleSize;
        // END_INCLUDE (calculate_sample_size)
    }

用法

   private Bitmap mBackground;
   private Drawable mBackgroundDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            LinearLayout linearLayout = (LinearLayout) findViewById(R.id.parent);
            final Resources res = getResources();
            int[] dimensions = Util.getDisplayDimensions(this);
            mBackground = ImageResizer.decodeSampledBitmapFromResource(res, R.drawable.bg, 100, 100, false);
            mBackgroundDrawable = new BitmapDrawable(res, mBackground);
            linearLayout.setBackground(mBackgroundDrawable);
         }

    @Override
    protected void onDestroy() {
        recycle();
        super.onDestroy();
    }

    private void recycle() {
        if (mBackground != null) {
            mBackground.recycle();
            mBackground = null;
            if (mBackgroundDrawable != null)
                mBackgroundDrawable = null;

        }
    }

注意: 如果您应用 true 作为第三个参数,它可以帮助您使用 Bitmap.Config.RGB_565.

有效地减小图像大小
         if (isLow) {
             options.inPreferredConfig = Bitmap.Config.RGB_565;
           }

Finally, research about OOM.