问题描述
我对内存泄漏以及可能导致它们的原因有基本的了解.这就是为什么我不明白我的代码是否有问题还是误报.由于项目不小,不知道该分享哪一部分代码.但请在评论中告诉我,我会添加所需的代码.
I have a basic knowledge of memory leaks and what can cause them. That's why I don't understand if I have a problem in my code or is it a false positive. I don't know which part of the code I should share since the project is not small. But just let me know in the comments and I will add required code.
我使用导航拱组件并遵循 MVVM 模式.我在项目开发后期添加了 LeakCanary 库,当我在屏幕之间导航时,它立即开始向我发出有关保留实例的警告.
I use navigation arch component and follow MVVM pattern. I added LeakCanary library later in the development of project and it immediately started to give me warnings about retained instances when I navigate between screens.
当我将片段添加到返回堆栈时会出现问题.随着每个添加到返回堆栈的片段,保留实例的计数器增加.当达到阈值 5 LeakCanary 转储堆并提供报告.
The problem occurs when I add fragments to the back stack. With each added fragment to the back stack the counter of retained instances increases. When it reaches the threshold value of 5 LeakCanary dumps the heap and provides report.
但是,如果我单击后退按钮并返回到前一个屏幕,则保留实例的计数器会减少,最终,当返回到第一个屏幕时,所有保留的实例都会消失.
But if I click on back button and return to previous screens then counter of retained instances decreases and eventually, when returned to 1st screen all retained instances disappear.
如果我查看堆分析报告,它说变量 coordinatorLayout 是对 xml 中 CoordinatorLayout
的引用已经泄漏.如果我删除该变量及其所有用法并再次运行该应用程序,我会看到同样的问题,但现在另一个变量是对 xml 中另一个视图的引用.我试图删除 LeakCanary 报告为泄漏的所有视图及其使用情况.当它说一个 TextView
正在泄漏时,它只是用于在 onViewCreated
中设置文本而没有在其他任何地方使用,我开始怀疑我的代码.
If I look at heap analysis reports it says that the variable coordinatorLayout which is a reference to the CoordinatorLayout
in xml has leaked. If I remove the variable and all of its usage and run the app again I see the same problem, but now with another variable that is a reference to another view in xml. I tried to remove all of the views and their usage that LeakCanary reported as leaking. When it said that a TextView
, which is just used to set a text in onViewCreated
and not used anywhere else, is leaking I started to doubt that there is a problem in my code.
我分析了片段中的生命周期方法调用,并注意到当我导航到前一个片段的新屏幕时,所有方法直到并包括 onDestroyView
都被调用,但不是 onDestroy
.当我点击返回 onDestroy
时,会为位于后堆栈顶部的片段调用 onDestroy
,并且保留实例计数器减少.
I analyzed the lifecycle method calls in fragments and noticed that when I navigate to new screen for previous fragment all methods till and including onDestroyView
gets called but not onDestroy
. When I click back onDestroy
is called for fragment that was on top of back stack and retained instances counter decreases.
我怀疑导航组件在返回堆栈中时保留了片段的实例,而 LeakCanary 将其视为泄漏.
I suspect that Navigation component is keeping the instance of a fragment when it is in back stack and LeakCanary is seeing it as a leak.
推荐答案
这就是后端堆栈上的 Fragment 的工作方式(而 Navigation 仅使用现有的 Fragment API):Fragment 的视图被销毁,但 Fragment 本身并未被销毁 -它们保持在 CREATED
状态,直到您点击后退按钮并返回到 Fragment(之后 onCreateView()
将再次被调用,您将返回到恢复
).
That's how Fragments on the back stack work (and Navigation just uses the existing Fragment APIs): the Fragment's view is destroyed, but the Fragment itself is not destroyed - they are kept in the CREATED
state until you hit the back button and return to the Fragment (after which onCreateView()
will be called again and you'll move back up to RESUMED
).
根据 片段:过去、现在和未来谈话,未来的变化之一使用 Fragments 是一种选择,可以销毁后端堆栈上的 Fragment,而不是具有两个单独的生命周期.目前还没有这个功能.
As per the Fragments: Past, Present, and Future talk, one of the future changes coming to Fragments is an opt in option to destroy Fragments on the back stack, rather than having two separate lifecycles. This isn't available as of yet.
您必须清除对 onDestroyView
中的视图的引用,因为这是 Fragment 系统不再使用该视图的标志,如果它不是,则可以安全地进行垃圾收集供您继续参考视图.
You have to null out your references to the views in onDestroyView
as that's the sign that the view is no longer being used by the Fragment system and it can be safely garbage collected if it wasn't for your continued reference to the View.
这篇关于导航 Arch 组件是否会造成误报内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!