BitmapFactory.DecodeByteArray导致增长堆(frag情况)

本文关键字:frag 情况 DecodeByteArray BitmapFactory | 更新日期: 2023-09-27 18:27:01

我正在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错误。正如你所看到的,我已经在那里4次将图像加载到imageview。所以,我想知道是否有人和我有同样的问题?我花了好几个小时试图通过查看这里(以及其他地方)来解决这个问题,但我找不到解决方案。请记住,我正在用Xamarin(c#语言-使用Android库)编写应用程序。

很抱歉有糟糕的链接,但我还没有足够的信誉在这里上传图片:)

BitmapFactory.DecodeByteArray导致增长堆(frag情况)

我看到的第一件事是使用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运行时去掉它:

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);
}