我对内存泄漏以及导致内存泄漏的原因有基本的了解。这就是为什么我不明白我的代码是否有问题或者是误报。由于项目不小,我不知道应该分享哪部分代码。但请在评论中告诉我,我将添加所需的代码。
我使用导航拱门组件并遵循 MVVM 模式。我后来在项目开发中添加了 LeakCanary 库,当我在屏幕之间导航时,它立即开始向我发出有关保留实例的警告。
当我将片段添加到返回堆栈时,就会出现问题。随着每个添加到返回堆栈的片段,保留实例的计数器都会增加。当达到阈值 5 时,LeakCanary 转储堆并提供报告。
但是,如果我单击后退按钮并返回到先前的屏幕,则保留实例的计数器就会减少,最终,当返回到第一个屏幕时,所有保留的实例都会消失。
如果我查看堆分析报告,它会说变量 coordinatorLayout 是对CoordinatorLayout
xml中已经泄露。如果我删除该变量及其所有用法并再次运行应用程序,我会看到同样的问题,但现在另一个变量是对 xml 中另一个视图的引用。我尝试删除 LeakCanary 报告泄漏的所有视图及其用法。当它说一个TextView
,它只是用来设置文本onViewCreated
并且没有在其他地方使用,正在泄漏我开始怀疑我的代码中有问题。
我分析了片段中的生命周期方法调用,并注意到当我导航到上一个片段的新屏幕时,所有方法直到并包括onDestroyView
被呼叫但没有onDestroy
。当我点击返回时onDestroy
调用位于返回堆栈顶部的片段,并且保留实例计数器减少。
我怀疑导航组件在返回堆栈中时保留了片段的实例,而 LeakCanary 将其视为泄漏。
这就是后台堆栈上的 Fragment 的工作方式(导航仅使用现有的 Fragment API):Fragment 的视图被销毁,但 Fragment 本身并没有被销毁 - 它们被保存在CREATED
状态,直到您点击后退按钮并返回到 Fragment(之后onCreateView()
将再次被呼叫,您将返回到RESUMED
).
根据片段:过去、现在和未来 https://youtu.be/RS1IACnZLy4?t=957,未来对片段的更改之一是选择销毁返回堆栈上的片段,而不是具有两个单独的生命周期。目前尚不可用。
您必须取消对以下视图的引用onDestroyView
因为这表明该视图不再被 Fragment 系统使用,并且如果您不继续引用该视图,则可以安全地对其进行垃圾收集。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)