通过位图加载UI时出现OutOfMemory异常

时间:2016-08-24 14:49:40

标签: android performance bitmap

我尝试使用位图获取OutOfMemory异常来加载我的UI。我之前使用过PNG,然后将它们转换为GIF,希望通过加载位图来减少内存使用量。图像总数为291kb(使用PNG时大约为2.2mb)。

如果图像比屏幕尺寸大很多,我使用inSampleSize来加载图像:

public void loadViewImage(View view, int drawableID) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), drawableID, options);
        options.inSampleSize = calculateInSampleSize(options, view.getWidth(), view.getHeight());
        options.inJustDecodeBounds = false;
        view.setBackgroundDrawable(new BitmapDrawable(BitmapFactory.decodeResource(getResources(), drawableID, options)));
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    while (height / inSampleSize > reqHeight || width / inSampleSize > 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;
        }
    }

    return inSampleSize;
}

然后通过以下方式加载图像:

final RelativeLayout backgroundLayout = (RelativeLayout)findViewById(R.id.backgroundLayout);
backgroundLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom,
                                   int oldLeft, int oldTop, int oldRight, int oldBottom) {
            loadViewImage(backgroundLayout, R.drawable.background);
        }
    });

此应用适用于三星Galaxy S7 Edge但不适用于LG G2。当使用inSampleSize 2时,它确实如此,但我想知道这些291kb图像如何使用这么多内存。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

人们告诉你尺寸并不重要。文件大小并不重要。与PNG相比,GIF对JPG也不是。重要的是图像大小(以像素为单位)。 Bitmap对象是未压缩的,而文件是压缩的。这意味着每个像素需要4个字节(加上一些小到可以忽略的开销)。因此,1440x2560图像大约为370万像素 - 或大约15MB。每个人都占用了那么多的记忆。缩放它将需要更多 - 您必须解码至少部分原始缩放它(它可能需要两个单独大小的总和)。

通常,当您看到OOM错误时,问题是如何在整个代码中使用内存,而不仅仅是在一个地方。检查这种情况的最佳方法是通过堆分析查找失控对象创建/保留。虽然非常大的图像(例如来自新设备上常见的1200万像素相机的图片)可能会在缩放时引起很多问题 - 仅图像就需要50MB。除非您正在加载大量全屏图像,否则这不应该是一个问题。如果你是,你应该在手工完成后回收它们。如果您有很多这样的布局活动并且可能有深层堆栈,您可能需要考虑删除onPause中的图像并在onResume中重新加载以节省内存。