可绘制文件夹上的Android Out of Memory错误

时间:2015-11-18 12:17:52

标签: android out-of-memory runtime-error

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

3 个答案:

答案 0 :(得分:2)

drawable相当于drawable-mdpi

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

如果您在drawable-xhdpi中放置相同大小的图片,则只会在较大的xxhdpi设备上对其进行上采样,而在其他设备上进行下采样。<​​/ p>

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

答案 1 :(得分:0)

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

有用的备忘单:http://i.stack.imgur.com/kV4Oh.png

答案 2 :(得分:0)

对于管理Out Of Memory Error,您可能需要做的一件事是通过压缩图像来缩小图像大小并将其保存在可绘制的文件夹中。这对于减少应用程序大小以及运行时的内存消耗非常有用。

或者您可能需要使用以下类来降低图像尺寸宽高比。

<强> 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;
           }
  

最后,关于OOM的研究。