gpt4 book ai didi

android - 为什么我没有得到内存不足异常?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:29:24 24 4
gpt4 key购买 nike

我在可绘制文件夹中有一张高分辨率图像 (2588*1603)。如果我使用下面的代码 (1) 为 imageView 设置它,我不会得到 OOM 异常并且图像按预期分配:

public class MainActivity extends ActionBarActivity{


private ImageView mImageView;

int mImageHeight = 0;
int mImageWidth = 0;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mImageView = (ImageView) findViewById(R.id.imageView);
mImageView.setScaleType(ScaleType.FIT_CENTER);

BitmapFactory.Options sizeOption = new BitmapFactory.Options();
sizeOption.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.a, sizeOption);
mImageHeight = sizeOption.outHeight;
mImageWidth = sizeOption.outWidth;

mImageView.post(new Runnable() {
@Override
public void run() {
try {
BitmapRegionDecoder bmpDecoder = BitmapRegionDecoder
.newInstance(getResources().openRawResource(R.drawable.a),true);
Rect rect = new Rect(0,0,mImageWidth, mImageHeight);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDensity = getResources().getDisplayMetrics().densityDpi;
Bitmap bmp = bmpDecoder.decodeRegion(rect, options);

mImageView.setImageBitmap(bmp);

} catch (NotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});

}
}

请注意,矩形大小与图像大小完全相同。

但是如果我使用其他方法,例如 2 或 3,我会出现 OOM。

  2)  mImageView.setBackgroundResource(R.drawable.a);

3) Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.a);
mImageView.setImageBitmap(bmp);

1 和 2,3 有什么区别?

(我知道如何解决OOM,我只想知道区别)

最佳答案

这是BitmapRegionDecoder#decodeRegion的来源:

public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
checkRecycled("decodeRegion called on recycled region decoder");
if (rect.left < 0 || rect.top < 0 || rect.right > getWidth()
|| rect.bottom > getHeight())
throw new IllegalArgumentException("rectangle is not inside the image");
return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, options);
}

如您所见,它只是调用了一个本地方法。我对 C++ 了解不够,无法查看该方法是否缩小了位图(根据您的 inDensity 标志)。

其他两种方法使用相同的本地方法(nativeDecodeAsset)来获取位图。

编号 2 缓存 可绘制对象,因此需要更多内存。
经过大量操作(检查位图是否已经预加载或缓存等),它调用本地方法来获取位图。然后,它缓存可绘制对象并设置背景图像。

数字 3 非常简单,它在几次操作后调用本地方法。


结论:对我来说,很难说哪种情况适用于此,但应该是这两种情况之一。

  1. 您的第一次尝试缩小位图(inDensity 标志),因此需要更少的内存。
  2. 这三种方法都需要或多或少相同数量的内存,数字 2 和 3 只是多一点点。您的图像使用 ~16MB RAM,这是某些手机上的最大堆大小。数字 1 可能低于该限制,而其他两个略高于阈值。

我建议你调试这个问题。 在你的 list 中,设置 android:largeHeap="true" 以获得更多内存。然后,运行 3 次不同的尝试并记录堆大小和位图分配的字节数。

long maxMemory = Runtime.getRuntime().maxMemory();
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long freeMemory = maxMemory - usedMemory;
long bitmapSize = bmp.getAllocationByteCount();

这会给你一个更好的概览。

关于android - 为什么我没有得到内存不足异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29988812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com