java.lang.OutOfMemoryError:位图大小超出 VM 预算 - android - 多少图像?

Posted

技术标签:

【中文标题】java.lang.OutOfMemoryError:位图大小超出 VM 预算 - android - 多少图像?【英文标题】:java.lang.OutOfMemoryError: bitmap size exceeds VM budget - android - how many images? 【发布时间】:2010-12-29 15:17:47 【问题描述】:

我正在开发一个 android 应用程序,当我阅读并为自己学习时,我不能同时在屏幕上显示很多图像,否则会出现异常。

问题是我可以在屏幕上同时拥有多少张图片或多少 KB 的图片或多少个布局/图片。

我知道这不是唯一影响记忆的事情,但我正在寻找一个数字,以便我可以围绕它进行计划。

谢谢

丹尼尔


编辑:

我刚刚在 android 开发网站 (http://developer.android.com/resources/articles/future-proofing.html) 上找到了这个

要避免的技巧,#3:过度使用布局

由于视图渲染基础架构的变化,布局中不合理的深度(超过 10 个左右)或过宽(总共超过 30 个)视图层次结构现在可能会导致崩溃。对于过于复杂的布局来说,这总是存在风险,但您可以认为 Android 1.5 在暴露这个问题方面比 1.1 更好。大多数开发人员无需担心这一点,但如果您的应用程序布局非常复杂,则需要节食。您可以使用更高级的布局类(如 FrameLayout 和 TableLayout)来简化布局。

我想这可能是我的问题。

当它说'broad'时,它是在说最后一层吗?

谢谢

丹尼尔

【问题讨论】:

相关:***.com/questions/1949066/… 非要问,买不起。 【参考方案1】:

我发现开发 Android 应用程序的最常见错误之一是

java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget 错误。

我经常在更改方向后使用大量位图的 Activity 上发现此错误:Activity 被销毁,再次创建,并且布局从 XML 中“膨胀”,消耗了可用于位图的 VM 内存。

前一个活动布局上的位图没有被垃圾收集器正确释放,因为它们交叉引用了它们的活动。经过多次实验,我找到了一个非常好的解决这个问题的方法。

首先,在 XML 布局的父视图上设置 id 属性:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_
     android:layout_
     android:id="@+id/RootView"
     >
     ...

然后,在 Activity 的 onDestroy() 方法上,调用 unbindDrawables() 方法,将引用传递给父 View,然后执行 System.gc()

    @Override
    protected void onDestroy() 
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
    

    private void unbindDrawables(View view) 
        if (view.getBackground() != null) 
        view.getBackground().setCallback(null);
        
        if (view instanceof ViewGroup) 
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) 
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            
        ((ViewGroup) view).removeAllViews();
        
    

这个 unbindDrawables() 方法递归地探索视图树并且:

移除所有背景可绘制对象的回调 删除每个视图组上的子项

【讨论】:

你的逻辑帮我解决了内存不足的异常......非常感谢分享这么棒的逻辑【参考方案2】:

这个答案有两部分

1) 不是屏幕有多少图像,而是在完成活动时小心清理所有内容

2) (Future-Proofing Your App)

要避免的技巧,#3:过度使用布局

由于视图渲染基础架构的变化,布局中不合理的深度(超过 10 个左右)或过宽(总共超过 30 个)视图层次结构现在可能会导致崩溃。对于过于复杂的布局来说,这总是存在风险,但您可以认为 Android 1.5 在暴露这个问题方面比 1.1 更好。大多数开发人员无需担心这一点,但如果您的应用程序布局非常复杂,则需要节食。您可以使用更高级的布局类(如 FrameLayout 和 TableLayout)来简化布局。

丹尼尔

【讨论】:

【参考方案3】:

内存量因设备而异,您必须使用的内存量取决于系统当时正在执行的其他操作。如果可以提供帮助,最好的办法就是不要让系统内存不足。你在做什么需要屏幕上显示这么多图像?

【讨论】:

是的,我在屏幕上有很多图像,它一次又一次地崩溃如何解决它。【参考方案4】:

这取决于手机的 HEAP 大小。 因此,如果您的应用程序获得的堆比提供的电话多,那么它可能会产生问题。

新一代安卓设备包含。这里是一些列表

HTC Wildfire (2.2.1) = 16MB。 HTC Wildfire S (2.3.5) = 20MB。 HTC 莎莎 (2.3.3) = 20MB。 HTC Desire (2.3.3) = 32MB。 HTC Desire S (2.3.5) = 32MB。 三星 Galaxy S GT-I9000 (2.2) = 48MB。 三星 Galaxy R GT-I9103 (2.3.5) = 64MB。 三星 Galaxy Y GT-S5360 (2.3.5) = 64MB

因此没有特定的解决方案,但您可以尝试优化位图大小。 例如在使用后回收位图。或使用从 sampleSize 中提取的 bitmapFectory 制作另一个。

如果您使用的是模拟器,那么您可以创建一个包含更多堆大小的设备,以便在您的 avd 管理器中将新的额外硬件配置添加为 VM 堆大小 = 32 或更高。

【讨论】:

那只适用于模拟器,不适用于真机,所以不是解决方案

以上是关于java.lang.OutOfMemoryError:位图大小超出 VM 预算 - android - 多少图像?的主要内容,如果未能解决你的问题,请参考以下文章