为什么重新启动活动时堆内存会增加? [英] Why does heap memory increase when re-launching an activity?

查看:21
本文介绍了为什么重新启动活动时堆内存会增加?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与 Android 中的内存有关.

This question concerns memory in Android.

我的方法:

我有两个活动,A 和 B.从 A,我像这样启动 B:

I have two activites, A and B. From A, I launch B like this:

Intent i = new Intent(A.this, B.class);
startActivity(i);

点击 B 中的按钮,我这样做:

On button click in B, I do this:

B.this.finish();

  • 在 B 中,我覆盖了 onDestroy 方法并将所有引用设置为 null.
  • 我没有在 A 的 onResume 方法中分配新的内存.
  • 我没有泄露上下文.
  • 我没有使用多线程.
  • 我没有使用服务.
  • B中的所有变量都是私有类变量,在B的onDestroy中都设置为null.
  • 此外,B 中的 ImageViews 在 B 的 onDestroy 中将其背景设置为 null.
  • 我确信 B 会被销毁.
  • 结果:

    当我在活动 A 中时,堆内存为 7.44 MB.然后当我启动 B 并在 B 上调用完成时(从而返回到 A),堆增加了 0.16 MB.再次重复这个过程,heap 每次增加 0.08 MB.

    When I am in Activity A, heap memory is at 7.44 MB. Then when I start B and call finish on B(and thus returning to A), heap is increased by 0.16 MB. Repeating this process again, heap is increased by 0.08 MB every time.

    • 我不是在看堆限制,我在看分配的堆.
    • 我在 B 的 onDestroy 方法结束时调用 System.gc().

    附加信息:

    -我已经使用 MAT 来分析内存分配并尝试找到此泄漏.奇怪的是,Activity B 似乎有 5 个实例.碰巧的是,我重复了 startActivity/finish 过程 5 次.最下面的条目是Activity,其他的是Activity中的监听器:

    -I have used MAT to analyse memory allocations and try to find this leak. Something strange is that Activity B seems to have 5 instances. As it so happens, I was repeating the startActivity/finish process 5 times. The bottom entry is the Activity, the others are listeners in the activity:

    这是支配树的截图.我找不到任何异常或可疑之处.

    And this is screenshot of the dominator tree. I can't find anything unusual or suspect.

    -我已经观看了关于内存使用(和泄漏)的两个谷歌 IO 视频.

    -I have watched both google IO videos on memory usage(and leaks).

    问题:

    无论我做什么,这 0.08 MB 的堆是否有可能总是被分配(并且不能被 GC 收集)?如果没有,您知道是什么原因造成的吗?

    Is it possible that this 0.08 MB of heap will always be allocated(and not collectable by the GC) no matter what I do? If not, any idea of what might be causing this?

    更新:

    1. 我尝试在没有在 B 中设置内容视图的情况下启动活动 B.这意味着 B 是一个完全空的活动.结果是当我多次重新启动活动时,堆内存没有增加.但是请注意,这不是解决方案.我必须能够设置内容视图.

    1. I tried to launch activity B without setting a content view in B. This means that B is a completely empty activity. The result was that the heap memory did NOT increase when I'm relaunching the activity several times. Note, however, that this is no solution. I must be able to set a content view.

    scorpiodawg:我尝试在模拟器上运行我的应用程序,但堆仍在增长.试试吧.

    scorpiodawg: I tried running my app on an emulator, and the heap still grows. Good try though.

    ntc:在可能的情况下,我将所有出现的this"更改为getApplicationContext()".我无法调用 setContentView(getApplicationContext());因为 setContentView 需要对布局文件的引用,而不是上下文.我所做的是创建一个空的布局文件并调用 setContentView(emptylayout);在活动 B 的 onDestroy 方法中.这没有帮助.

    ntc: I changed all occurences of "this" to "getApplicationContext()" where it was possible. I could not call setContentView(getApplicationContext()); because setContentView wants a reference to a layout file, not a context. What I did instead was to create an empty layout file and call setContentView(emptylayout); in the onDestroy method of Activity B. That did not help.

    我试图删除所有代码,以便只调用 setContentView(mylayout).问题依然存在.然后我删除了布局 XML 文件中的所有 gui 元素.问题依然存在.唯一剩下的是容器视图,几个嵌套的线性、相对和滚动布局.我试图删除滚动条中的android:scrollbarDefaultDelayBeforeFade"属性设置.结果很好,内存泄漏消失了.然后我放回了之前删除的所有代码,但没有设置android:scrollbarDefaultDelayBeforeFade"属性,内存泄漏又回来了.这有多奇怪?

    I tried to remove all the code so that only setContentView(mylayout) gets called. Problem persisted. Then I removed all the gui elements in the layout XML file. Problem persisted. The only thing that was left was the container views, a couple of nested linear, relative and scrolllayouts. I tried to remove setting the "android:scrollbarDefaultDelayBeforeFade" attribute in the scrollbar. The result was great, the memory leak had vanished. Then I put back all the code I previously removed but didn't set the "android:scrollbarDefaultDelayBeforeFade" attribute and the memory leak was back. How strange is that?

    推荐答案

    如果您有 5 个活动 B 的实例,那么您没有正确管理活动堆栈.我发现检查它的最佳方法是使用 CLI 命令:

    If you have 5 instances of activity B, then you are not managing the activity stack correctly. I find the best way to check it is with the CLI command:

    adb shell dumpsys meminfo '你的应用程序包名称'

    当我在两个活动项目之间切换时,我遇到了类似的问题.每次切换时,我都会在堆栈中获得一个新实例,如上述命令所示.然后,我将已启动活动的标志设置为 FLAG_ACTIVITY_REORDER_TO_FRONT,代码如下:

    I had a similar problem in a two activity project when I switched between them. Every time I switched I got a new instance on the stack as revealed by the above command. I then set the flags for the launched activities to FLAG_ACTIVITY_REORDER_TO_FRONT with code like:

    Intent i = new Intent("com.you.yourActivityB");
    i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    startActivity(i);
    

    完成此操作后,当我在两个活动之间切换时,adb shell 命令不会显示更多实例

    Once I'd done this, then the adb shell command did not show more instances of my two activities when I switched between them

    这篇关于为什么重新启动活动时堆内存会增加?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆