了解Android应用程序中的内存泄漏 我对java编程很陌生,有很多C++经验,我在阅读如何引用会导致Android应用程序内存泄漏。我被难住了。在“第二课”中,它说:

了解Android应用程序中的内存泄漏 我对java编程很陌生,有很多C++经验,我在阅读如何引用会导致Android应用程序内存泄漏。我被难住了。在“第二课”中,它说:,java,android,memory-leaks,Java,Android,Memory Leaks,关键是,活动不知道某个对象的生命周期将在活动实例结束时结束。如果该对象保留在内存中,它也将在内存中保存该活动[…] 在我看来(可能是错误的;请纠正我),当活动结束时,SomeObject被销毁(假设不存在对它的其他引用)。活动引用的是某个对象,而不是相反。我不明白为什么这里会泄露任何信息,更不用说整个活动了。这与他们正在为EventListener创建一个匿名类有关 public void onResume() { super.onResume(); SomeObject ob

关键是,活动不知道某个对象的生命周期将在活动实例结束时结束。如果该对象保留在内存中,它也将在内存中保存该活动[…]


在我看来(可能是错误的;请纠正我),当活动结束时,
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);
}
public void onResume(){
super.onResume();
SomeObject=新的SomeObject();
setSuccessListener(新的EventListener(){
public void onEvent(布尔响应){
Log.d(标签名称,“有效响应?”+响应);
}
});
SomeObjectManager.getSingleton().addObject(对象);
}
  • 明确指出,这是在活动的 onResume()

  • 匿名类(以及非静态内部类)具有对其周围类的隐式引用。因此,在本例中,EventListener有一个对活动本身的引用

  • 因此,SomeObject引用了活动,因为它引用了实现EventListener的匿名类

以下是您在问题中引用的引用之前的文本:

例如,在上面的示例中:我们附加了对 活动实例到某个对象,可能是持久的,并且在 某个地方的经理。关键是

因此,SomeObjectManager类在活动被销毁时不会消失,它持有对SomeObject的引用,而SomeObject持有对EventListener的引用,后者反过来引用活动

所以当你说:

在我看来(可能是错的;请纠正我),当活动 结束时,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);
}
这有帮助吗?

答案如下:

如果可以这样做,请在调试器中运行此命令,并在以下位置设置断点:

Log.d(TAG_NAME, "Valid response? "+response);
现在检查“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);
object.setSuccessListener(新的EventListener(){
public void onEvent(布尔响应){
Log.d(标签名称,“有效响应?”+响应);
}
});
SomeObjectManager.getSingleton().addObject(对象);
现在的链条是:

SomeObjectManager->singleton->listofObjects->object

对于目标:

对象->成功侦听器->匿名事件侦听器->此$


这$here是活动的外部实例。

不幸的是,活动很容易泄漏。我认识的一些Android开发人员很高兴(有时是故意)忘记了这一事实。感谢你的关心,知道你想了解更多,以避免这种情况

泄露活动的一些常见方法

1) 将活动设置/添加/注册为侦听器或观察者,并忘记设置(null)/删除/注销活动

2) 使用静态引用而不是清除静态引用,将对活动的引用传递给任何保留它的内容。(单身就是一个例子)

3) 使用非静态内部类。(匿名内部类处理程序就是一个例子)

您可以采取一些措施来避免此类泄漏

1) 请记住设置(空)/删除/取消注册您的活动

2) 作为软件设计的一部分,将活动生命周期的概念融入到处理活动的组件中

3) 将内部类设为静态,如果需要外部类的引用,请使用WeakReferences

4) 尽可能使用应用程序上下文,而不是活动上下文

您的活动将被销毁并重新创建的一些常见情况

1) 如果您允许在应用程序中更改方向,则从纵向切换到横向时,活动将被销毁并重新创建,反之亦然

2) 使用设备的“后退”按钮退出应用程序将导致当前活动被破坏(即使应用程序本身仍将保持运行)

3) 虽然更为罕见,但Android可以随意终止您的活动,以释放资源并让设备对用户保持响应

您应该熟悉Android Studio的设备监视器、hprof conv工具和Eclipse内存分析器工具。我发现,测试我的应用程序是否泄漏活动的最简单方法是,在我进入应用程序时,在设备监视器中对其进行内存配置,使用设备返回按钮退出应用程序,然后通过单击应用程序托盘中的图标或进入最近状态返回应用程序。重复几次,然后创建一个内存转储文件。在此转储文件上运行hprof conv工具,将其转换为MAT可以理解的格式,然后在MAT中打开它


有很多关于获取内存配置文件和使用MAT的教程。做一个网络搜索。

Luiggi:我不认为这是关于singleton对象管理器的。google开发者有一个非常好的视频,特别是他们用来演示这一点的示例代码,即拥有一个内部类并将其实例放入一个静态变量中。s