记忆和活动:: OutOfMemory

时间:2012-01-26 17:41:13

标签: android memory themes

设置:

我有这个应用程序,它在线性路径中有4个活动,非常简单的导航: A - > B - > C - > D

所有活动共享相同的背景图像,并且都有一些常规按钮,textview或edittext。所有这些都在单独的视图中定义xml文件。

背景是渐变,有点沉重。大约3兆作为未压缩的位图。

该应用程序尚未执行任何操作,其唯一的逻辑是启动活动并按下按钮点击它们

我尝试使用MAT来查找内存泄漏但找不到任何内容。我的应用程序中保留的最大大小为656(ko?),应用程序的总保留大小为1520(ko?),我找不到任何可复制的对象。 顺便说一下,dumpsys显示27300(ko?)已分配

问题:

  1. 当我向上导航时,我发现内存使用量相当于背景大小。
  2. 当我向下导航时,使用后退按钮或结束命令关闭活动时,应用程序的内存使用量不会减少。
  3. 如果我从A转到D然后回到B并旋转屏幕,应用程序将以OutOfMemory异常关闭。
  4. 问题:

    更新:我想真正的问题是为什么我有一个巨大的内存泄漏(一次5兆),冻结时应用程序大小为27megs,我在MAT中看不到它?

    1. 为什么Android会在同一背景下多次解压缩,每次活动一次?似乎效率低下。
    2. 是否可以通过使用主题来解决这个问题,或者我会看到相同的“按活动分配1个背景”的怪异?
    3. 为什么关闭后不收回活动?
    4. 为什么MAT和dumpsys呈现不同的数字?
    5. 线索信息

      在同一时间我有: dumpsys meminfo:

      Applications Memory Usage (kB):
      Uptime: 74006853 Realtime: 110962243
      
      ** MEMINFO in pid 22683 [com.kayenko.sosadresse] **
                          native   dalvik    other    total
                  size:    20820     5767      N/A    26587
             allocated:    18751     2901      N/A    21652
                  free:      312     2866      N/A     3178
                 (Pss):     1357      201    16782    18340
        (shared dirty):     2264     1804     5456     9524
          (priv dirty):     1280      116    16032    17428
      
       Objects
                 Views:        0        ViewRoots:        0
           AppContexts:        0       Activities:        0
                Assets:        2    AssetManagers:        2
         Local Binders:       18    Proxy Binders:       16
      Death Recipients:        1
       OpenSSL Sockets:        0
      
       SQL
                     heap:        0         MEMORY_USED:        0
       PAGECACHE_OVERFLOW:        0         MALLOC_SIZE:        0
      

      这个统治者树:

      MAT Dominator tree

      任何人都知道我想要寻找的东西。

3 个答案:

答案 0 :(得分:7)

在Android中,内存是一个非常棘手的主题。

每个应用都会根据设备获得堆内存限制。此堆内存是dalvik内存加本机内存,您可以将其视为dumpsys meminfo结果中的总列。 dalvik内存处理除了位图之外的所有内容,这些内容在本机内存中分配(在Honeycomb之前的Android版本中也是如此)。

说过我只能回答你的一些问题:

  1. 据我所知,Android将始终为Bitmaps分配内存,即使它们是相同的。因此,在您的情况下,每个活动都会为您的背景分配内存。

  2. 我不知道使用主题是否更好,你必须尝试。

  3. 一方面,当设备有足够的内存来处理下一个活动时,不会回收活动。当您按下后退按钮时,每个活动都被推到一堆。如果Android需要更多内存,它会从堆中删除一个活动来释放其内存(回到第一个问题,也许这就是不共享内存的原因)。另一方面,您可以设置活动launchMode来更改此行为(看看here)。

  4. 我认为MAT不显示本机内存数据。使用dumpsys meminfo的原生列查看您为位图分配的内存量。

  5. 我自己很难处理OutOfMemory问题。现在我有一个更明确的想法  它是如何工作的,我能够使用大文件而不会耗尽内存。我强烈推荐这两个对我有帮助的资源:

    祝你好运!

答案 1 :(得分:4)

因此经过数小时的调查和Xavi的帮助后,结果如下:

问。为什么Android会在同一背景下多次解压缩,每次活动一次?似乎效率低下。

一个。尽管通过某种方式让位图在各个活动之间共享似乎是合乎逻辑的,因为我们处于内存很少的移动设备上,但这似乎并不存在于Android中。每次在不同的活动中使用位图时,它都会被解压缩到本机内存。

问。是否有可能通过使用主题来克服这个问题,或者我会看到相同的“按活动分配一个位图”的怪异?

在实验之后,使用主题消耗的内存与在布局的xml中明确设置位图所使用的内存量完全不同。这对我来说很奇怪,因为样式是关于将属性分组到同一个地方。

问。为什么关闭后不收回活动?

一个。嗯,我不确定,但我发现,这几乎只有在调试时才会给我OOM错误。从设备启动应用程序时,几乎从未发生过。调试过程中出现故障?在你完成5个小时测试之前尝试一下。

问。为什么MAT和dumpsys呈现不同的数字?

一个。 Xavi的答案是正确的,dumpsys meminfo显示分配的所有内存(native + dalvik),而MAT只显示Dalvik。由于位图像素在本机存储器中分配,因此MAT不会看到它。这在Android 3.0之前才有效,他们改变了分配方案并使位图的像素数据适合Dalvik。

问。我是如何解决我的问题的

一个。首先,这可能不是一个问题,不调试。其次,为了安全起见,我用一个带有径向渐变的形状替换了渐变png并使用了

getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);

在我的活动中创建以避免绑扎。我仍然会在一些设备上使用条带,但我宁愿使用条带而不是FC

答案 2 :(得分:0)

当您销毁活动时,您需要显式回收用作背景的位图。代码将是这样的:

@Override
protected void onDestroy () {
    Drawable drawable = getView().getBackground();
    if (drawable instanceof BitmapDrawable) {
        ((BitmapDrawable)drawable).getBitmap().recycle();
    }
    drawable.setCallback(null);
    getView().setBackgroundDrawable(null);
    super.onDestroy();
}

也许您需要为嵌套视图递归释放资源,但这取决于您的布局结构。这是一般情况