避免内存泄漏的好方法

时间:2017-01-02 19:46:05

标签: java android mvvm memory-leaks garbage-collection

我正在尝试使用Android数据绑定的MVVM。我的代码如下:

public class ... extends Activity {    
        ...            
        private CommentViewModel viewModel;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, provideLayout());
            viewModel = new CommentViewModel(this);
            binding.setViewModel(viewModel);
        }

        @Override
        protected void onDestroy() {
            viewModel = null; //setting view model to null to avoid leaks
            super.onDestroy();
        }
}

我想要做的是在ViewModel中将onDestroy()设置为null以避免任何可能的泄漏。

由于我的ViewModel本身会将一些callbacks注册到其他组件并使用可能泄漏的context,如果其中一个回调未被删除且上下文传递到某处,我决定设置它空。

但是我的同事开了一个有趣的讨论,他说这是一个过时的做法,因为'Effective Java'表明这就是你在C ++中的表现。他说,一个好方法是从ViewModel中删除所有回调,而不是将其设置为null。类似的东西:

public class ... extends Activity {    
        ...            
        private CommentViewModel viewModel;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            ...//same as above
        }

        @Override
        protected void onDestroy() {
            viewModel.removeCallbacks(); //removing all callbacks from view model to avoid leaks
            super.onDestroy();
        }
}

现在这两种方法都运行良好,但在第一种方法中,我非常确信泄漏不会发生。但结果,它看起来有些难看。第二种方法很好但它迫使我考虑ViewModel中可能发生的所有可能的泄漏。

这可能是一个普遍的问题:您认为哪种方法更好,为什么?

1 个答案:

答案 0 :(得分:0)

一般来说,让JVM做它的工作。

没有比像

这样的事情更令人恼火的了
System.gc()

在大型应用的生产代码中。中间件工程师的工作就是调整JVM以及如何管理内存 - 我真的像这些人一样说话。在你的情况下,事情是相同的,开发Android的人最了解如何管理GC。如果不能使任何更清晰/更容易理解的代码,你就不应该编写更多的代码。

另一方面

经验丰富的程序员应该知道与框架相关的所有肮脏技巧(例如:stackoverflow.com/questions/13534030/can-a-scheduled-future-cause-a-memory-leak)以及如何不取消,而不是取消引用,关闭等可能会导致内存泄漏。

在你的情况下,更重要的是,你可以想象会有相当复杂的回调(让我们说它们是循环的,并且有数千个),并且使你的引用为空赢了# 39;为GC更容易,但删除回调将会。