【问题标题】:Android ListView Row Background's causing OutOfMemory IssueAndroid ListView 行背景导致 OutOfMemory 问题
【发布时间】:2012-01-05 11:03:55
【问题描述】:

我有一个片段,它从 web 服务中提取数据并将其显示在 ListView 中。我有 10 种不同的选择器可用于行背景。循环后,背景会重复。

我面临的问题是设备(Galaxy Nexus!)无法处理显示所有这些背景。当我通过 setbackgroundResource 设置背景时,操作系统会不断调用 GC 来释放内存,这使得 ListView 滚动非常不稳定。

所以我尝试缓存所使用的 Drawable。我看到了改进,但由于缓存了多少 Drawable,设备最终会抛出 OutOfMemory 异常。举例说明缓存了多少,我需要所有 10 个选择器,每个选择器都包含两个可绘制对象,加上第一个和最后一个,因为它们是不同的。这是内存中的 24 个可绘制对象。

现在,我想这可能是我正在使用的图像的大小,我需要缩小它们并按比例拉伸,但我不确定这是否可行。

有什么建议吗?我花了几天时间不停地研究这个问题,但还没有找到可行/接近的解决方案。

谢谢

亚当

【问题讨论】:

    标签: android listview background bitmap out-of-memory


    【解决方案1】:

    Mimminito,

    您所描述的问题困扰着 Android 平台上的许多开发人员。这样做的原因是,当 Google 实现 View Drawables 时,他们必须做出一个有效的假设,即可能需要保留之前的 Drawable。这是因为越来越多的平台上越来越多的应用程序需要这种行为。

    最终,有多种方法可以缓解这些问题,但没有一种包罗万象的解决方案。

    1. 替换背景时,获取原始背景。如果是位图,recycle() 它。如果它是 Drawable,请将引用设置为 null 并通过 setCallback 删除其回调(这在您更改方向或切换活动时尤其重要)。

    2. 图形是最消耗内存的资源之一。如果您使用的是 Drawable 或 Bitmap,它每像素使用 4 个字节。但是,如果必须调整图像大小才能正确显示,那么无论应用程序是放大还是缩小尺寸,它实际上都会使用更多。以高分辨率创建图形很棒,但对于移动设备,您希望将其缩放到您实际使用的尺寸。

    3. 如果您使用大量图形,您可以考虑只使用那些将要可见的图形。也就是说,如果您有 32 个项目,但只有 3 个是可见的,则只加载可见的 3 个,可能还有一些直接的邻居。可以为许多标准化控件实施延迟加载。

    4. 我建议查看 .9.png 文件。这些非常适合优化图形。

    5. 如果您的按钮有文本,请不要在图形文件上绘制它。允许 Android 将文本放在图形文件上。它的处理方式大不相同,内存消耗大大减少。虽然它可能不那么美观,但它会增加可靠性(这就是你在这里的原因)

    6. 在某些情况下,可能希望图形是平面位图,而不是压缩格式。这减少了处理器和内存的负载,但以文件大小为代价。这是因为压缩格式必须在内存中解压缩才能使用,但在文件实际关闭之前不会释放内存。 (这甚至不包括用于解压缩它的运行时代码的内存,并且当应用程序必须调整图形大小时成本更高)。

    7. 添加一些额外的 System.gc() 语句可以帮助减轻负载,但它并不可靠,因为它只会告诉系统它已准备好尽早进行垃圾回收。

    8. 最后,您可以根据设备的分辨率拥有多种尺寸。这是您可以通过您的应用程序传输的信息。这就是我们必须在本地应用程序中支持多设备的方式。

    所有这些建议可能会有所帮助,但信息量很大。希望我为您提供了足够的信息,让您可以实施满足您需求的解决方案。

    希望这会有所帮助, 模糊逻辑

    【讨论】:

    • 感谢您的回复。确实它有很多信息,其中一些可能会有所帮助。我的第一个想法是调整图像的大小,以便按密度缩放,因为我使用的原件非常大。我会看看这有什么帮助,接下来我很可能也会给它们打九个补丁。最大的问题是,当允许系统全部处理它时(通过在 getView() 中设置背景资源),ListView 在快速滚动时变得太不稳定,因为它试图一次加载这么多的可绘制对象。
    【解决方案2】:

    也许您将 cacheColorHint 设置为透明(如果您有固定的背景图像):android:cacheColorHint="#00000000"。对我来说,它也多次调用 GC。

    我发现设置以下属性会禁用 android 的列表视图缓存并且列表滚动平滑(不再经常调用 GC):

    android:scrollingCache="false"
    android:animationCache="false"
    

    另外,如果你想摆脱默认选择颜色,请使用:

    android:listSelector="#00000000"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多