2014-10-17 45 views
1

我正在Xamarin中开发一个Android应用程序。我在从字节流生成图像时遇到问题。 BitmapFactory(这似乎是最流行的解决方案),导致巨大的分配问题 - 增长堆。BitmapFactory.DecodeByteArray导致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

请在发布您的代码,而不是链接到它的照片,这些链接可能会在未来死去这也使得更难以阅读。 – 2014-10-17 09:00:05

+0

嗨,我需要10个或更多的声誉,所以我现在不能这样做。我在这里是一个新手,所以我的声望仍然是1 :) – 2014-10-17 09:07:25

+0

你可以在你的问题中发表文字,然后将其标记为代码,并且它将被正确格式化,这不需要任何声望点。 – 2014-10-17 09:09:13

回答

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,你会发现他们使用它。

然后,他们要确保加载Bitmapusing声明并将其分配给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阵列,因为它包含人l图像的像素。

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

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

Hi @ Cheesebaron。我想创建的图像是从一个字节流,它不是在资源中找到(所以我不能使用Decoderesources)。您正在使用的方法调用结构在我正在拍照并保存时已经使用。在那里我也缩小了比例。但它不是给出问题的结构,它是当我使用这种方法BitmapFactory.DecodeByteArray。如果我使用你的代码,只用DecodeByteArray进行修改,那么我会得到更多的Grow Heap错误,因为方法DecodeByteArray会被调用两次(在DecodeSampledBitmapFromArray中)。 – 2014-10-19 13:36:24

相关问题