这个问题涉及Android中的记忆。
我的方法:
我有两个活动,A和B.从A,我这样推出B:
Intent i = new Intent(A.this, B.class);
startActivity(i);
按钮点击B,我这样做:
B.this.finish();
结果:
当我在活动A中时,堆内存为7.44 MB。然后,当我启动B并在B上调用完成(从而返回到A)时,堆增加了0.16 MB。再次重复此过程,堆每次增加0.08 MB。
其他信息:
- 我使用MAT来分析内存分配并试图找到这个漏洞。奇怪的是,活动B似乎有5个实例。碰巧的是,我重复了startActivity / finish过程5次。底部条目是活动,其他条目是活动中的监听器:
这是统治者树的截图。我找不到任何不寻常或怀疑的东西。
- 我已经观看了关于内存使用量(和泄漏)的谷歌IO视频。
问题:
无论我做什么,是否有可能始终分配这个0.08 MB的堆(并且不能由GC收集)?如果没有,任何可能导致这种情况的想法?
更新
我试图在B中没有设置内容视图的情况下启动活动B.这意味着B是一个完全空的活动。结果是当我多次重新启动活动时堆内存没有增加。但请注意,这不是解决方案。我必须能够设置内容视图。
scorpiodawg:我尝试在模拟器上运行我的应用程序,堆仍在增长。不错的尝试。
ntc:我将所有出现的“this”更改为“getApplicationContext()”。我无法调用setContentView(getApplicationContext());因为setContentView需要对布局文件的引用,而不是上下文。我做的是创建一个空的布局文件并调用setContentView(emptylayout);在活动B的onDestroy方法中。这没有帮助。
我尝试删除所有代码,以便只调用setContentView(mylayout)。问题持续存在。然后我删除了布局XML文件中的所有gui元素。问题持续存在。唯一剩下的就是容器视图,几个嵌套的线性,相对和滚动布局。我试图删除滚动条中的“android:scrollbarDefaultDelayBeforeFade”属性。结果很好,内存泄漏消失了。然后我放回了我之前删除的所有代码但没有设置“android:scrollbarDefaultDelayBeforeFade”属性并且内存泄漏又回来了。这有多奇怪?
答案 0 :(得分:11)
如果您有5个活动B实例,那么您没有正确管理活动堆栈。 我发现检查它的最佳方法是使用CLI命令:
adb shell dumpsys meminfo'您的应用包名称'
当我在它们之间切换时,我在两个活动项目中遇到了类似的问题。每次我切换时,我都会在堆栈上看到一个新实例,如上面的命令所示。然后,我将已启动活动的标志设置为FLAG_ACTIVITY_REORDER_TO_FRONT,代码如下:
Intent i = new Intent("com.you.yourActivityB");
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
一旦我完成了这个,那么当我在它们之间切换时,adb shell命令没有显示我的两个活动的更多实例
答案 1 :(得分:3)
似乎您在该活动中有内存泄漏。
可能你正在泄露上下文(在这种情况下的活动)。因此,请确保在活动中调用onDestroy方法时,正在清理对上下文的所有引用。 More details here
另外,请查看完成活动后未注册的可能内容观察者。
答案 2 :(得分:2)
我认为,这是一个典型的java问题。杀死一个Activity并不意味着它的关联对象应该从heap
中删除,即使它们在丢失的土地上(它们的引用为空)。因为它在调用Garbage collector
时完全依赖虚拟机(无论你说System.GC()
)。因此当条件几乎没有记忆时它会调用并清理它(不能再确定,可能会在它们被引用后立即变为null
),所以我认为你不应该担心它。
<强>编辑:强>
致电setContentView(getApplicationContext);
以及this
关键字在哪里传递上下文,请将其更改为this.getApplicationContext()
答案 3 :(得分:1)
答案 4 :(得分:0)
无论我做什么,是否有可能始终分配这个0.08 MB的堆(并且不能通过&gt; GC收集)?如果没有,任何可能导致这种情况的想法?
当系统认为需要时,将回收0.08MB的堆(如果未使用)。一旦调用System.gc(),垃圾收集就不会发生,它更像是在可能的情况下尽快发生GC的请求。在分配对象和从内存中删除对象之间通常会有 LONG 时间。 Java虚拟机规范和Java语言规范指定了经历以下阶段的对象的生命周期:
请注意,当一个对象无法访问时,它只会成为垃圾收集的候选者,因为它可能发生。 即使像Dalvik这样占地面积小的JVM,我也不认为物体会在短时间内经历整个寿命。 GC是一项昂贵的操作,因此仅在需要时才进行。
如果您有快速(由于某种原因)需要从内存中删除的对象,请尝试WeakReference。或者也许你可以提供更多关于你想要做什么的背景信息,而且有人能够以这种方式帮助你。
有关GC如何在Java中发生的更多信息, this is a pretty good article