Android ListView行背景导致OutOfMemory问题

时间:2012-01-05 11:03:55

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

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

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

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

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

有什么建议吗?我已经花了几天不间断地工作,并没有找到可行/紧密的解决方案。

由于

亚当

2 个答案:

答案 0 :(得分:6)

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. 最后,您可以根据设备的分辨率设置多种尺寸。这是您可以通过您的应用程序传输的信息。这就是我们如何在本地应用程序中执行多个设备支持。

  9. 所有这些建议可能有所帮助,但其中包含大量信息。希望我能为您提供足够的解决方案,以满足您的需求。

    希望这有帮助, FuzzicalLogic

答案 1 :(得分:0)

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

我发现设置以下属性会禁用android的列表视图缓存,列表会顺利滚动(GC不会再被调用):

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

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

android:listSelector="#00000000"