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.
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.
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.
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.
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.
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.
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which is no longer needed is not released. A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code.
DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a computer's RAM due to poorly designed or programmed applications that fail to free up memory segments when they are no longer needed.
To avoid memory leaks, memory allocated on heap should always be freed when no longer needed.
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
).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With