安卓 - 即使在onDestroy()方法中将实例设置为null,Activity仍然会泄漏

3

我在主Activity(NavigationActivity)中遇到了内存泄漏问题。

public static NavigationActivity navigationActivity;

public static NavigationActivity getNavigationActivity() {
    return navigationActivity;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);

    navigationActivity = NavigationActivity.this;

}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (navigationActivity != null) {
        navigationActivity = null;       
    }      
}

哪里泄漏?如何修复它?非常感谢您的帮助。

我正在使用LeakCanary,这是泄漏情况: enter image description here


我查了一下你的个人资料,发现你根本不接受答案。你应该为了未来的读者这样做,这样他们就知道哪个答案是正确的。因此,我给你点踩。 - Vygintas B
你能否在LeakCanary截图中打开NavigationActivity (+) stacktree?这个NavigationActivity类是什么? - sytolk
4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
1
将实例变成一个 WeakReference
private final WeakReference<Activity> navigationActivity;

同样,onDestroy()不能保证被调用。想要了解更多关于onDestroy()的内容,请点击这里


1

onStop方法中,你应该将活动实例设置为null,因为可能不会调用onDestroy

来自Android开发者文档

protected void onDestroy ()

在API level 1中添加。在activity销毁之前执行任何最终清理工作。这可能是因为activity正在结束(某人调用了finish()),或者是因为系统暂时销毁此活动实例以节省空间。您可以使用isFinishing()方法区分这两种情况。

注意:不要指望这个方法会被调用来保存数据!例如,如果一个activity正在content provider中编辑数据,则应该在onPause()或onSaveInstanceState(Bundle)中提交这些编辑,而不是在这里。通常,此方法用于释放与activity相关联的线程等资源,以便销毁的activity在其应用程序的其余部分仍在运行时不会留下这些东西。有些情况下,系统将简单地杀死activity的主机进程,而不在其中调用此方法(或任何其他方法),因此不应将其用于希望在进程消失后继续存在的事情。


1
相反,我会说清除对象类似于释放资源,这是清理我们不再需要的对象的好地方。 - Dharmendra

1
你已经清除了活动中的引用。但是类ContactsCompletionView仍然对你的活动有强引用。避免此泄漏的最好方法是不要暴露与你的活动的链接。
但是,如果你真的需要这个,你可以使用对你的ActivityWeakReference。所以你的getNavigationActivity()方法可能会像这样:
public static WeakReference<NavigationActivity> navigationActivityRef;
{
    public static WeakReference<NavigationActivity> getNavigationActivity() {
      if(navigationActivityRef == null) {
          navigationActivityRef = new WeakReference<>(this);
      }
      return navigationActivityRef;
}     

1
尝试使用 <\p>。
@Override
protected void onStop() {
    super.onStop();
    navigationActivity = null;
}

但是使用Activity的静态引用是非常糟糕的做法,不要这样做。

在大多数情况下,您可以使用activity.this引用或类似于getActivity()方法的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,