2011-04-06 74 views
0

经过对完整产品的一些测试后,我刚刚发现我所有的硬件设备都具有较大的VM堆。Android,关注虚拟机堆大小

最低的是32MB。

我的应用程序是一个内存密集型应用程序,加载一堆高质量的alpha图像并将它们作为动画绘制到画布上。最多可以加载两组这些加载的内容(一个用于当前动画,另一个用于下一个)

我现在担心在将其中一个设备上的VM堆大小减少到16MB后,它不会事实上在堆大小很小的设备上运行。

由于我不能对图像的大小做很多工作,并且我无法做到减少图像的数量,所以我问如何才能在不太严格的内存限制下获得相同的结果?

谢谢

回答

0

当你说高质量,你的意思是高分辨率?我的建议是,你只在内存中存储你需要在屏幕上显示的内容,并将其余的文件存储在文件系统上。然后,您可以在后台以块处理它。不知道这是否适合你,我不太了解你的应用的功能。

+0

好吧,高质量我的意思是图像都加载并显示为ARGB_8888,其他响应者缩放它们的建议并不有用,因为所有图像的创建尺寸都与它们在屏幕上显示所需的尺寸完全相同。本质上,应用程序创建图像的小动画。想想它就像我在运行时创建southpark情节一样。加载的唯一图像是用于“场景”的图像,当切换到下一个时,我拥有当前和下一个“场景”的图像。图像本质上是“场景”中任何移动主体的“部分”。 – Hamid 2011-04-06 20:55:20

+0

基于这里的解决方案不是加载图像的方法而被接受,因为无论如何,它们仍然必须被位图解码,但是只有当前使用的图像需要保存在内存中。 – Hamid 2011-08-01 23:54:16

0

您可以使用此方法来解码图像。它可能会使它们更轻。请记住,图像在显示增加其内存消耗时会变成位图。

public static Bitmap decode(byte[] imageByteArray, int width, int height) { 
    // Decode image size 
    BitmapFactory.Options o = new BitmapFactory.Options(); 
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length, 
      o); 

    // Find the correct scale value. It should be the power of 2. 
    int width_tmp = o.outWidth, height_tmp = o.outHeight; 
    int scale = 1; 
    while (true) { 
     if (width_tmp/2 < width || height_tmp/2 < height) 
      break; 
     width_tmp /= 2; 
     height_tmp /= 2; 
     scale *= 2; 
    } 

    // Decode with inSampleSize 
    BitmapFactory.Options o2 = new BitmapFactory.Options(); 
    o2.inSampleSize = scale; 
    o2.inTempStorage = new byte[Math.max(16 * 1024, width * height * 4)]; 
    return BitmapFactory.decodeByteArray(imageByteArray, 0, 
      imageByteArray.length, o2); 

    // return BitmapFactory.decodeByteArray(imageByteArray, 0, 
    // imageByteArray.length); 
} 

其中

宽度 - 在该ImageView的可能像素最大宽度。 高度 - imageView可能具有的最大像素高度(以像素为单位)。

这样,位图会变得更轻,应用程序可能会消耗更少的内存。

(注:我复制此方法并修改了它一点点,我不记得原来的问题,所以我不能把URL)

我用strore图像的字节数组,我只解码他们就在展示他们之前。

现在,就像James L所说,最好将图像保存在文件系统中,并且只在需要时才会记忆,但如果你不这样做(我的情况)。你可以下载图片:

public static byte[] getBytes(InputStream is) throws IOException { 

    int len; 
    int size = 1024; 
    byte[] buf; 

    if (is instanceof ByteArrayInputStream) { 
     size = is.available(); 
     buf = new byte[size]; 
     len = is.read(buf, 0, size); 
    } else { 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     buf = new byte[size]; 
     while ((len = is.read(buf, 0, size)) != -1) 
      bos.write(buf, 0, len); 
     buf = bos.toByteArray(); 
    } 
    return buf; 
} 

public static byte[] downloadFileByteArray(String fileUrl) 
      throws IOException, MalformedURLException { 

    URL myFileUrl = null; 

    myFileUrl = new URL(fileUrl); 

    HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection(); 
    conn.setDoInput(true); 
    conn.connect(); 
    InputStream is = conn.getInputStream(); 

    return getBytes(is); 
} 

如果媒体链接在内存中的图像,你将能够通过我提出的方法寻找热塑成型将它们变成字节数组。

除此之外(并调用System.gc()),你可以做的事情并不多(据我所知)。也许在onPause()和onDestroy()中使用BMP并在onResume()中重新构造它们(如果需要的话)。

+0

这里有一种offtopic – fazo 2011-04-06 19:18:22

+0

我在加载“一堆高质量”时就遇到了VM堆大小的问题,就像@Hamid解释说的那样。我通过使用这种方法解决了它。我开始以jpg fotmat格式将图像存储在RAM中,而不是Drawable或Bitmap格式,即诅咒,除非当前显示图像。我一直在努力减少内存消耗。这不完全是他要求的,但它可能有助于解决他的问题。现在修改解码方法的任何格式,而不是字节数组应该很容易实现。使用该方法可以大大减少内存消耗。 – 2011-04-07 01:10:56

+0

当然,这只会让事情变得更糟?我不仅要在内存中存储字节阵列,而且还要在显示图像时为其提供位图数据。在我的标准用例中,即使不是所有的图像都是一次显示,也几乎都有。 – Hamid 2011-04-07 09:12:33