BitmapFactory.DecodeByteArray导致Grow Heap(frag case)

我正在开发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:  #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库)。

对不起糟糕的链接,但我没有足够的信誉在这里上传图像:)

我看到的第一件事是你使用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文档中有效加载大位图的文档,您会发现它们只是用它来使用它。

然后他们确保在using语句中加载Bitmap并将其分配给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); }