【问题标题】:Android, concern over VM heap sizeAndroid,对虚拟机堆大小的关注
【发布时间】:2011-04-06 15:14:36
【问题描述】:

在对一个完整的产品进行了一些测试后,我刚刚发现我拥有的硬件设备都有很大的 VM Heaps。

最低为 32MB。

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

在将我的一台设备上的 VM 堆大小减小到 16MB 后,我现在担心它实际上无法在堆大小这么小的设备上运行。

由于我对图像的大小无能为力,而且我也无能为力来减少图像的数量,我问我如何在不那么严格的内存限制的情况下获得相同的结果?

谢谢

【问题讨论】:

    标签: android bitmap virtual-machine heap-memory


    【解决方案1】:

    当您说高质量时,您是指高分辨率吗?我的建议是您只将需要在屏幕上显示的内容存储在内存中,并将其余的存储在文件系统中。然后,您可以在后台分块处理它。不确定这是否适合您,我不太了解您的应用程序是做什么的。

    【讨论】:

    • 好吧,所谓高质量,我的意思是图像全部加载并显示为 ARGB_8888,其他受访者建议缩放它们没有用,因为所有图像都是按照显示所需的大小创建的屏幕上。本质上,该应用程序创建了很少的图像动画。把它想象成我在运行时创建 Southpark 剧集。加载的唯一图像是当前“场景”的图像,当切换到下一个时,我有当前和下一个“场景”的图像。图像本质上是“场景”中任何移动主体的“部分”。
    • 接受是因为这里的解决方案不是加载图像的方法,因为无论哪种方式,它们仍然需要进行位图解码,而是只保留当前使用的图像记忆。
    【解决方案2】:

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

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

    在哪里

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

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

    (注意:我复制了这个方法并稍微修改了一下,我不记得原来的问题所以我不能放网址)

    我用来将图像存储在字节数组中,并且只在显示它们之前对其进行解码。

    现在,就像 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() 中重新构建它们。

    【讨论】:

    • 我在加载“一堆高质量”时遇到了 VM 堆大小的问题,就像@Hamid 解释的那样。我通过使用这种方法解决了它。我开始以 jpg fotmat 而不是 Drawable 或 Bitmap 格式将图像存储在 ram 中,这很糟糕,除非此时正在显示图像。我这样做是为了减少内存消耗。这不完全是他所要求的,但它可能有助于解决他的问题。现在修改解码方法任何格式而不是字节数组应该很容易完成。使用该方法可以大大减少内存消耗。
    • 这肯定只会让事情变得更糟吗?我不仅必须在内存中拥有字节数组,而且在显示图像时,也需要它的位图数据。在我的标准用例中,我几乎可以同时显示所有图像。
    • 当我这样做的时候,我不知道你已经准备好只显示需要的内容了。我刚刚阅读了您对另一个答案的评论,在您的 casi 中,我认为将图片保存在文件系统上会更好。如果您同时显示少量位图(并且不想在设备上保存图片),这是一个很好的解决方案。有了这个,我已经能够在 ram 上拥有一个 51 张图片的全屏画廊,而无需保存任何设备,拥有 100kb 的图片。
    • 我只是想到了一些东西,有一种方法可以知道android中的VMHeap,我记不太清了,但是一个朋友曾经给我看过。您也许可以检查堆大小,并根据它,有一组质量较低的图像,以在需要时减少堆需求。这不是最佳选择,但它可能让您在低 VM 堆设备上播放动画。这是我能想到的最好的。如果您想要获取VM hep的方法,我也许可以找到它,告诉我,我会寻找它。
    猜你喜欢
    • 2013-02-18
    • 1970-01-01
    • 2012-12-23
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多