Mar 30 | 7:20 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Mar 30 | 7:40 PM |
Eric | has entered the room |
Mark M. |
hello, Eric!
|
Mark M. |
how can I help you today?
|
Eric |
mark, nice to see you again
|
Eric |
I was wondering about a leakcanary trace I saw
|
Mark M. |
um, OK -- not sure if I can help with that, but if you can provide the trace (ASCII text or screenshots, I guess), I can try
|
Eric |
my activity contains fragment A and fragment B. fragment A contains a strong reference to an adapter. If I navigate to fragment B and don't null my adapter I see 2 leaks. 1 for recyclerview and 1 for a ConstraintLayout. My confusion is because my app layouts do not use ConstraintLayout but leakcanary says it is a leak
|
Mark M. |
is something still holding a reference to fragment A after you navigate to fragment B?
|
Mar 30 | 7:45 PM |
Eric |
no, and my fragment A layout lacks a ConstraintLayout.
|
Mark M. |
then I'd at what is holding onto fragment A
|
Mark M. |
actually, I made an assumption which may not be correct
|
Mark M. |
what is Leak Canary saying has the reference to the RecyclerView and the ConstraintLayout?
|
Eric |
after my recylclerview leak it points to a constraintlayout leak and states "ObjectWatcher was watching thiw because Fragment A received Fragment onDestroyView callback (references to its views should be cleared to prevent leaks"
|
Eric |
Fragment A adapter contains a ObservableData-->Observers-->my recyclerview
|
Mark M. |
I do not know what ObservableData is -- is that from a library?
|
Mar 30 | 7:50 PM |
Mark M. |
or do you mean Observable from RxJava?
|
Eric |
it is a member type inside RecyclerView.Adapter from Android sdk
|
Mark M. | |
Mark M. |
that search comes up empty
|
Mark M. |
so there does not appear to be anything named ObservableData in the Jetpack
|
Eric |
It is actually spelled AdapterDataObservable and exists as a member of nested class Adapter inside of RecyclerView
|
Mark M. |
ah, OK, now I see it
|
Mark M. |
and your fragment A is holding onto the adapter? if so, then I'm back to my earlier recommendation: identify what is holding onto fragment A
|
Mark M. |
or, null out the field that holds the adapter in onDestroyView()
|
Mark M. |
in principle, if nothing has a reference to fragment A, Leak Canary should not care, though I have not been using its latest version and it may be getting more sensitive than I am used to
|
Mar 30 | 7:55 PM |
Mark M. |
but, the message of the complaint is fairly accurate: ideally, after onDestroyView(), your fragment does not have any direct or indirect references to views created in onCreateView() or during the operation of the fragment
|
Mark M. |
if the fragment is going to get garbage collected right away, usually there is no harm in ignoring onDestroyView()
|
Eric |
my recyclerview leaks because AdapterDataObsewrvable contains observers, one being my recyclerview. To fix both leaks I set my adapter to null. I don't see this ConstraintLayout being referred to by LeakCanary. Just trying to understand it
|
Eric |
To my understanding nothing is referring to fragment A
|
Mark M. |
are your item layouts for the RecyclerView using anything from the Jetpack or Material Components for Android? perhaps they are using the ConstraintLayout
|
Eric |
nope, AppCompatTextViews
|
Mark M. |
¯\_(ツ)_/¯
|
Mark M. |
it is very difficult for me to help on something like this, that is tied to some debugging output that I cannot see
|
Eric |
true. One last question
|
Eric |
why do people write constants inside of a companion object?
|
Mark M. |
the approach that I take depends on who needs the constant
|
Mark M. |
a private constant I will usually just put outside the class at the top of the Kotlin source file
|
Mar 30 | 8:00 PM |
Mark M. |
but if other classes need the constant, then I put it in a companion object to avoid polluting the top-level namespace across the project
|
Mark M. |
personally I do not see the value in having private constants in a companion object, but that's just me
|
Eric |
if I put it outside my class, and a different class needs to use it, I use a wider access modifier. I don't know why it is bad to put it in a top-level namespace ("polluting it")
|
Mark M. |
how many developers are working on your project?
|
Eric |
I ask because I see it all the time and I don't see any benefit. It varies but it's a fairly large group of people
|
Mar 30 | 8:05 PM |
Mark M. |
in my experience, the bigger the team, the more likely it is that you are going to want to have some structure around naming things
|
Mark M. |
you're certainly welcome to do that solely by looking at the name of the constant itself, but I would rather see Thingy.COUNT than THINGY_COUNT
|
Mark M. |
but, again, it's a matter of personal taste and team policies
|
Mark M. |
in my case, if I rename Thingy to OtherThingy, I would rather have its associated constant follow along automatically (OtherThingy.COUNT) rather than also have to remember to rename a lightly-associated constant (OTHER_THINGY_COUNT)
|
Eric |
I guess belonging to a class if it is a companion gives you some context
|
Mark M. |
right -- for private constants, the context is the file, and ideally you don't have massive individual source files
|
Eric |
ok I appreciate it mark
|
Eric |
take it easy
|
Mark M. |
happy to help!
|
Mark M. |
you too!
|
Mar 30 | 8:10 PM |
Eric | has left the room |
Mar 30 | 8:25 PM |
Mark M. | turned off guest access |