BitmapFactory.De codeByteArray的成长造成堆(FRAG情况)情况、De、BitmapFactory、FRAG

2023-09-06 07:50:36 作者:情场智障ζ-ω-

我正在开发中Xamarin的Andr​​oid应用程序。我有从字节流生成图像的问题。 BitmapFactory(这似乎是最流行的解决方案),是造成巨大的分配问题 - 成长堆。

I am developing an Android app in Xamarin. I am having problems with generating an image from a bytestream. BitmapFactory (which seems to be the most popular solution), is causing huge allocation problems - 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.De codeByteArray的被调用的方法。它做工精细,显示图像。但它是缓慢的,并导致这些警告​​。

Above is the method where BitmapFactory.DecodeByteArray is being called. It works fine, the image is displayed. But it is slow and causes these "Warnings".

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

有关每次调用该方法,成长堆出现错误。正如你可以看到我已经加载的图像的ImageView的有4次。所以,我想知道如果任何人有同样的问题吗?我试过好几个小时来解决这个问题,通过寻找在这里(和其他地方),但我无法找到一个解决方案。请记住我写在Xamarin应用。(C#语言 - 采用Android库)

For everytime the method is called, Grow Heap error appears. As you can see i have loaded an image to an imageview 4 times there. So, i was wondering if anyone had the same problem as me? I tried for many hours to solve the problem, by looking in here (and else where) but i could not find a solution. Keep in mind i am writing the application in Xamarin (c# language - using Android library).

对不起,糟糕的链接,但我没有足够的名气上传图片来呢:)

Sorry for the lousy links, but i don't have enough cred to upload images here yet :)

推荐答案

我看到的第一件事情就是你用 InJustDe codeBounds ,这通常是用来获取像这样图像的宽度和高度:

First thing I see is that you use InJustDecodeBounds, which usually is used to get the width and height of the image like so:

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;

此通常用于获得图像的高宽比,比例缩小,而不是加载巨大图像到存储器之前

This is generally used to get the aspect ratio of the image, before scaling it down, instead of loading a huge image into the memory.

如果你看看在有关装入大的位图的有效的Xamarin文档中​​,你会发现,他们使用它只是文档。

If you take a look at the docs about loading large bitmaps efficiently in the Xamarin documentation you will find that they use it for just that.

然后,他们要确保加载位图使用语句,并将其分配给的ImageView 是这样的:

Then they make sure to load the Bitmap in a using statement and assign it to the ImageView like this:

using(var bmp = DecodeBitmap(some args))
    imageView.SetImageBitmap(bmp);

在这里您不需要情况下,位图以后你可以叫回收站()就可以了,这告诉Java Runtime,以摆脱它:

In cases where you don't need the Bitmap afterwards you can call Recycle() on it, which tells the Java Runtime to get rid of it:

using(var bmp = DecodeBitmap(some args)) {
    imageView.SetImageBitmap(bmp);
    bmp.Recycle();
}

所以,你需要做同样的事情,也可能与你的字节阵列,因为它包含了图像的所有像素。

So you need to do something similar, probably also with your byte array as it contains all the pixels for the image.

因此​​,使用中的文档模式,你可以做这样的事情:

So using the pattern in the docs you could do something like this:

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