Navigation Arch Component 会造成误报内存泄漏吗?

Could Navigation Arch Component create a false positive memory leak?

我对内存泄漏及其原因有基本的了解。这就是为什么我不明白是我的代码有问题还是误报。由于项目不小,我不知道应该分享哪部分代码。但是请在评论中告诉我,我会添加所需的代码。

我使用导航架构组件并遵循 MVVM 模式。我后来在项目开发中添加了 LeakCanary 库,当我在屏幕之间导航时,它立即开始向我发出有关保留实例的警告。

当我将片段添加到返回堆栈时出现问题。随着每个添加到返回堆栈的片段,保留实例的计数器增加。当达到阈值 5 时,LeakCanary 转储堆并提供报告。

但是,如果我单击后退按钮并 return 返回到先前的屏幕,则保留实例的计数器会减少,最终,当 return 进入第一个屏幕时,所有保留的实例都会消失。

如果我查看堆分析报告,它说引用 xml 中的 CoordinatorLayout 的变量 coordinatorLayout 已经泄漏。如果我再次删除变量及其所有用法和 运行 应用程序,我会看到同样的问题,但现在另一个变量是对 xml 中另一个视图的引用。我试图删除 LeakCanary 报告为泄漏的所有视图及其用法。当它说 TextView 只是用来在 onViewCreated 中设置一个文本而没有在其他任何地方使用时,我开始怀疑我的代码有问题。

我分析了片段中的生命周期方法调用并注意到,当我导航到前一个片段的新屏幕时,所有方法都被调用,包括 onDestroyView 但没有 onDestroy。当我单击返回时,onDestroy 被调用用于返回堆栈顶部的片段,并且保留的实例计数器减少。

我怀疑 Navigation 组件在返回堆栈中时保留片段的实例,而 LeakCanary 将其视为泄漏。

这就是 Fragment 在后台栈上的工作方式(Navigation 只使用现有的 Fragment API):Fragment 的视图被销毁,但 Fragment 本身没有被销毁 - 它们保持 CREATED 状态直到你点击后退按钮并 return 到片段(之后 onCreateView() 将再次被调用,你将返回到 RESUMED)。

根据 Fragments: Past, Present, and Future talk,Fragments 未来的变化之一是选择在后台销毁 Fragments 的选项,而不是有两个单独的生命周期。目前尚不可用。

您必须取消对 onDestroyView 中视图的引用,因为这是片段系统不再使用该视图的标志,如果不是您继续引用视图。