android - Navigation Arch 组件会造成误报内存泄漏吗?

标签 android kotlin memory-leaks android-architecture-navigation leakcanary

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

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

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

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

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

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

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

最佳答案

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

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

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

关于android - Navigation Arch 组件会造成误报内存泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59503689/

相关文章:

java - 如何在baseUrl中调用没有反斜杠的改造

android - 我一次可以观察多少个 Stateflow?

ios - NSString 中的内存泄漏 stringWithUTF8String : with ARC enabled

javascript - 在一页 session 中可以加载的 WebGL 纹理数量是否有限制?

kotlin - kotlin简写版本if(true)

c# - 托管堆 .Net 4.5 中的未知对象

android - 声明样式和样式之间的区别

android - 导航组件 NavDeepLinkBuilder 返回堆栈

java - 我想使用保存的首选项获取选定的单选按钮,但 Activity 没有打开?

android - 如何在不使用 ADB 的情况下在 Android 中自动化 Android 单元测试