首页 > 解决方案 > Navigation Arch 组件会造成误报内存泄漏吗?

问题描述

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

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

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

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

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

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

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

标签: androidkotlinmemory-leaksandroid-architecture-navigationleakcanary

解决方案


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

根据Fragments:过去、现在和未来的谈话,Fragments 的未来变化之一是选择在后台销毁 Fragment 的选项,而不是拥有两个独立的生命周期。目前尚不可用。

您必须取消对视图的引用,onDestroyView因为这表明 Fragment 系统不再使用该视图,并且如果不是为了您继续引用该视图,它可以安全地被垃圾收集。


推荐阅读