我正在开发Xamarin的Android应用程序。我在从字节流生成图像时遇到问题。 BitmapFactory(这似乎是最受欢迎的解决方案)正在导致巨大的分配问题 - Grow Heap。
ConnectToDb connect = new ConnectToDb ();
byte[] arr = connect.SelectImgByte(3,"Thea");
BitmapFactory.Options options=new BitmapFactory.Options();
options.InJustDecodeBounds = true;
bmp = BitmapFactory.DecodeByteArray (arr, 0, arr.Length/*,options*/);
_imageView.SetImageBitmap (bmp);
上面是调用BitmapFactory.DecodeByteArray的方法。它工作正常,图像显示。但它很慢并导致这些“警告”。
Thread started: <Thread Pool> #6
[dalvikvm-heap] Grow heap (frag case) to 22.596MB for 1997584-byte allocation
[Choreographer] Skipped 129 frames! The application may be doing too much work on its main thread.
[dalvikvm-heap] Grow heap (frag case) to 20.755MB for 1997584-byte allocation
[dalvikvm-heap] Grow heap (frag case) to 22.735MB for 1997584-byte allocation
[dalvikvm-heap] Grow heap (frag case) to 24.710MB for 1997584-byte allocation
每次调用该方法时,都会出现Grow Heap错误。正如您所看到的那样,我已将图像加载到imageview 4次。 所以,我想知道是否有人和我有同样的问题?我试了几个小时来解决这个问题,通过查看这里(以及其他地方),但我找不到解决方案。 请记住,我正在使用Xamarin编写应用程序(c#语言 - 使用Android库)。
对于糟糕的链接感到抱歉,但我还没有足够的信心在这里上传图片:)
答案 0 :(得分:0)
我看到的第一件事是您使用InJustDecodeBounds
,它通常用于获取图像的宽度和高度,如下所示:
var options = new BitmapFactory.Options {
InJustDecodeBounds = true,
};
using (var derp = BitmapFactory.DecodeResource(Resources,
Resource.Id.myimage, options)) { }
var imageHeight = options.OutHeight;
var imageWidth = options.OutWidth;
这通常用于在缩小图像之前获取图像的宽高比,而不是将大图像加载到内存中。
如果您查看Xamarin文档中的docs about loading large bitmaps efficiently,您会发现他们只是使用它。
然后他们确保在Bitmap
语句中加载using
并将其分配给ImageView
,如下所示:
using(var bmp = DecodeBitmap(some args))
imageView.SetImageBitmap(bmp);
如果您之后不需要Bitmap
,可以在其上调用Recycle()
,告诉Java Runtime摆脱它:
using(var bmp = DecodeBitmap(some args)) {
imageView.SetImageBitmap(bmp);
bmp.Recycle();
}
所以你需要做类似的事情,可能还有你的byte
数组,因为它包含图像的所有像素。
因此,使用文档中的模式,您可以执行以下操作:
byte[] arr = connect.SelectImgByte(3,"Thea");
using(var bmp = DecodeSampledBitmapFromArray(arr, scaledWidth, scaledHeight)) {
_imageView.SetImageBitmap(bmp);
bmp.Recycle();
}
public static int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
var height = (float)options.OutHeight;
var width = (float)options.OutWidth;
var inSampleSize = 1D;
if (height > reqHeight || width > reqWidth)
{
inSampleSize = width > height
? height/reqHeight
: width/reqWidth;
}
return (int) inSampleSize;
}
public static Bitmap DecodeSampledBitmapFromArray(byte[] pixels, int reqWidth, int reqHeight)
{
var options = new BitmapFactory.Options {
InJustDecodeBounds = true,
};
using (var dispose = BitmapFactory.DecodeResource(arr, 0, arr.Length, options)) { }
// Calculate inSampleSize
options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeResource(arr, 0, arr.Length, options);
}