[英]Understanding Memory Leaks in an Android application
我对Java编程很陌生,有很多C ++经验,而且我正在阅读有关引用如何导致Android应用程序内存泄漏的问题。 这个解释让我很难过。 在“第2课”中它说:
关键是,Activity不知道当Activity的实例结束时SomeObject的生命周期将结束。 如果该对象保留在内存中,它也会将该Activity保存在内存中[...]。
正如我所看到的那样(可能是错误的;请纠正我),当活动结束时, SomeObject
被销毁(假设没有其他参考存在)。 该活动引用SomeObject
,而不是相反。 我不明白为什么在这里泄露任何东西,更不用说整个活动了。
这与他们为EventListener创建一个匿名类的事实有关。
public void onResume() {
super.onResume();
SomeObject object = new SomeObject();
object.setSuccessListener(new EventListener<Boolean>() {
public void onEvent(Boolean response) {
Log.d(TAG_NAME, "Valid response? "+response);
}
});
SomeObjectManager.getSingleton().addObject(object);
}
它明确声明这是在Activity的onResume()中完成的。
匿名类(以及非静态内部类)具有对其周围类的隐式引用。 所以在这种情况下,EventListener引用了Activity本身。
因此,SomeObject具有对Activity的引用,因为它具有对实现EventListener的Anonymous类的引用。
这是您在问题中引用的引用之前的文本:
例如,在上面的示例中:我们将对Activity实例的引用附加到某个对象,可能是持久性的,并且在某个管理器中。 重点是...
因此SomeObjectManager类在活动被销毁时不会消失,它保存对SomeObject的引用,SomeObject保存对EventListener的引用,EventListener又引用Activity。
所以当你说:
正如我所看到的那样(可能是错误的;请纠正我),当活动结束时,SomeObject被销毁(假设没有其他参考存在)。 该活动引用SomeObject,而不是相反。
该逻辑中的缺陷是SomeObject通过EventListener引用该活动。
这有帮助吗?
答案如下:这是如何逃脱的?
如果你能这样做,那么在调试器中运行它并设置断点:
Log.d(TAG_NAME, "Valid response? "+response);
现在看看'this'实例有哪些成员。 特别是你对this$0
感兴趣。
所以电话很重要:
objectFromBefore.setSuccessListener(null);
看看之前发生了什么:
object.setSuccessListener(new EventListener<Boolean>() {
public void onEvent(Boolean response) {
Log.d(TAG_NAME, "Valid response? "+response);
}
});
SomeObjectManager.getSingleton().addObject(object);
现在链是:
SomeObjectManager - > singleton - > listofObjects - > object
和对象:
object-> successListeners-> anonymous EventListener-> this $
这个$这里是你的外部实例,即活动。
不幸的是,泄漏活动非常容易。 我所知道的一些Android开发者很高兴(有时是故意的)忘记了这个事实。 感谢你的关心,足以知道你想了解更多,以避免这种情况。
一些常见的方法可以泄漏活动
1)设置/添加/注册您的Activity作为侦听器或观察者,并忘记设置(null)/删除/取消注册Activity。
2)使用静态引用而不清除静态引用将对Activity的引用移到任何保留它的任何内容上。 (单身就是一个例子)
3)使用非静态内部类。 (匿名内部类处理程序就是这样的一个例子)
您可以采取一些措施来避免这些类型的泄漏
1)记住设置(null)/删除/取消注册您的Activity
2)作为软件设计的一部分,将处理Activity的组件烘焙到Activity生命周期的概念中。
3)使内部类静态,并且需要对外部类的引用,使用WeakReferences
4)尽可能使用应用程序上下文而不是Activity上下文。
您的活动将被销毁和重新创建的一些常见情况
1)如果您在应用程序中允许更改方向,则从纵向切换到横向时,活动将被销毁并重新创建,反之亦然。
2)使用设备的后退按钮退出应用程序将导致当前活动被销毁(即使应用程序本身仍将继续运行。)
3)虽然更为罕见,Android可以随意杀死您的Activity以释放资源并使设备对用户保持响应。
您应该熟悉Android Studio的设备监视器,hprof-conv工具和Eclipse Memory Analyzer工具。 我发现测试我的应用程序以查看它是否正在泄漏活动的最简单方法是在我进入应用程序时使用设备监视器中的内存配置文件,使用设备后退按钮退出它,然后返回到应用程序通过单击应用程序托盘中的图标或转到最近。 重复几次,然后创建一个内存转储文件。 在此转储文件上运行hprof-conv工具,将其转换为MAT可以理解的格式,然后在MAT中打开它。
有许多关于获取内存配置文件和使用MAT的教程。 只需进行网络搜索。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.