我尝试使用位图获取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图像如何使用这么多内存。
非常感谢任何帮助。
答案 0 :(得分:0)
人们告诉你尺寸并不重要。文件大小并不重要。与PNG相比,GIF对JPG也不是。重要的是图像大小(以像素为单位)。 Bitmap对象是未压缩的,而文件是压缩的。这意味着每个像素需要4个字节(加上一些小到可以忽略的开销)。因此,1440x2560图像大约为370万像素 - 或大约15MB。每个人都占用了那么多的记忆。缩放它将需要更多 - 您必须解码至少部分原始缩放它(它可能需要两个单独大小的总和)。
通常,当您看到OOM错误时,问题是如何在整个代码中使用内存,而不仅仅是在一个地方。检查这种情况的最佳方法是通过堆分析查找失控对象创建/保留。虽然非常大的图像(例如来自新设备上常见的1200万像素相机的图片)可能会在缩放时引起很多问题 - 仅图像就需要50MB。除非您正在加载大量全屏图像,否则这不应该是一个问题。如果你是,你应该在手工完成后回收它们。如果您有很多这样的布局活动并且可能有深层堆栈,您可能需要考虑删除onPause中的图像并在onResume中重新加载以节省内存。