Android内存不足预防

Posted

技术标签:

【中文标题】Android内存不足预防【英文标题】:Android out of memory prevention 【发布时间】:2011-07-31 14:09:12 【问题描述】:

我有一个显示从网上即时下载的缩略图(小图像)的列表。 在某些时候,该进程会耗尽内存。 如何判断可用内存即将用完,从而停止下载更多图片?

我想提前知道,以免内存不足。

注意: 这不是内存泄漏,只是大量下载的位图。

谢谢。

【问题讨论】:

我会详细说明一下。为了不把每张图片都下载好几次,我把下载的图片缓存在activity中,替换掉旧的图片——LRU。我想知道何时停止缓存或限制 LRU 的大小。 我也遇到了同样的问题,我试过软引用什么的...... 【参考方案1】:

您可以覆盖 Activity 的 onLowMemory() 方法来自定义处理此类场景

【讨论】:

我不想达到这一点并定义如下内容:如果已用内存达到 80%,则停止碰撞缓存 我没有调用这个方法,只是收到OOM Exception。 onLowMemory() 在 OOM 之前未调用 -1:onLowMemory 用于所有应用程序之间的总体内存消耗。这不是这里的问题。相反,这个应用程序正在达到其堆限制。 onLowMemory 无济于事。【参考方案2】:

您应该在创建位图时使用BitmapFactory.OptionsinSampleSize 选项。

另外,android: out of memory exception in Gallery 中的一些提示对我检查可用内存很有用。

【讨论】:

不管大小,如果我有太多的图像,最终,进程会耗尽内存。 当然。最终,您必须停止在有限数量的图像上。真正的问题应该是如何在可接受的范围内尽可能地突破这个限制。【参考方案3】:

我使用 SoftReference 来保存位图对象。该列表只需要当前可见的图像。因此,我永远不必担心空间不足。

缺点是当我看到图像时,向下滚动(导致一些 SoftReferences 清除位图),然后再次滚动回到同一个地方 - 图像再次下载:(

此外,SoftReferences 会很快被清除。我希望他们将内部位图保存更长时间。

【讨论】:

很像答案:***.com/questions/1945201/android-image-cache/… 现在,使用 LruCache 而不是 SoftReferences。为避免出现比您预期的更积极地清除引用的问题。 developer.android.com/training/displaying-bitmaps/…【参考方案4】:

1) 你必须是你自己的浏览器。

将拇指下载到 SDCard,而不是将它们保存在 RAM 中。在保存它们之前缩小/旋转它们,以便下次需要加载它们时,SDCard 中的负载是“免费的”,而不是互联网上的昂贵负载。 (即:像任何浏览器一样,使用本地文件缓存)。

释放您为此创建的任何临时位图对象。

了解如何使用“inSampleSize”参数以低于原始分辨率的分辨率解压缩位图。

如果您编写的文件以图像扩展名(.jpg 等)结尾,它们将出现在图库中,所以不要用明显的图像文件名保存您的拇指。

2) 创建分层缓存系统(Bitmap > SDCard > Internets)。

解压缩缩略图时,将其保存在 SoftReference 缓存中。如果您需要使用该缩略图,请从缓存中请求它。如果 VM 需要更多内存,您的 SoftReference 实例可能会返回 null。

如果您从位图缓存中获取 null,请检查您是否已将您的 url 放在 SD 卡上并从那里将其加载到位图缓存中。

如果您从文件系统中获取 null,则从 Internet 下载图像并将其保存到 SDCard 并将其粘贴到您的位图缓存中。

3) 释放未被使用的资源。

以同样的方式,确保在视图离开屏幕后立即从视图中清除位图(如果您的视图位于 ListView 或其他基于适配器的元素中,这本质上是“免费的”回收 View 元素)-- 但是,如果您使用位图实例化了 ImageView,并且它们没有立即显示在屏幕上,那么您可能正在浪费堆。

您可以简单地在 ImageView 上调用 setImageBitmap(null);,然后对 Bitmap 的引用将被删除(这样,如果唯一的 ref 是未使用的 SoftReference)。

4) 注意你所在的线程。

请记住,您必须从非 UI 线程下载位图(我们使用服务实例作为意图请求队列),并且您必须附加位图仅在 UI 线程中查看实例。

您需要创建一个良好的队列系统,将所有内容从 UI 线程加载到位图缓存中,然后使用 Handler 告诉您的位图缓存填充 UI 线程上的 ImageView。

5) 注意您的下载队列。

如果您像我们一样拥有拇指全尺寸图片,您需要手动使用优先队列在拇指请求之前放置图片请求,或者使用两个不同的下载缩略图和完整图像的服务(将其单独的 Intent 排入队列)。

否则,您可能会在一个充满拇指下载的屏幕上排队,但直到所有拇指都完成后才以完整图像响应。

6) 询问系统您有多少 RAM。

  Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo();
  Debug.getMemoryInfo(memoryInfo);

7) “onLowMemory()”没有达到你的预期。

当用户在手机上运行太多应用程序并且操作系统需要从所有正在运行的应用程序中恢复物理内存时。

这与耗尽应用程序 VM 堆完全分开,就像加载太多位图很容易做到的那样。

据我所知,您不会收到警告,只会崩溃(您可以通过上述调用跟踪内存信息)。

希望对尝试从互联网下载和显示拇指有所帮助。

米格

【讨论】:

重新使用“SoftReference”。现在,推荐使用 LruCache。 developer.android.com/training/displaying-bitmaps/… --- “过去,流行的内存缓存实现是 SoftReference 或 WeakReference 位图缓存,但不建议这样做。从 Android 2.3(API 级别 9)开始,垃圾收集器在收集软/弱引用,这使得它们相当无效。”

以上是关于Android内存不足预防的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio的JVM内存不足问题怎么解决

Android Studio的JVM内存不足问题怎么解决

Android下载文件内存不足的问题

内存不足错误:Android Studio 上的 Java 堆内存

内存不足时Android应用程序强制关闭

20+天后由于碎片导致内存不足错误android