Context (or “What brought this on?“)
A couple of months ago I had to create a lazily initialized singleton class for Android, a logger. If you’re now thinking “Gero, no! Singleton is an anti pattern, you shouldn’t use that!” I’m afraid I have to inform you that you know nothing, Jon Snow. But I’m not gonna be an Ygritte, so for you I’ll add some special explanations in a future post. (Also I’m not going to sleep with you. You’re welcome.)
The logger needed to include some app specific information to each logged string, for example the app’s version number. For this you usually need to access methods from the
Context class on Android. Every
Activity is also a
Context, so it was no problem to get that. There was one problem, however, and that has to do with the way Android handles those Activities. For the un-initiated: An
Activity is basically responsible for the UI, usually a (part of a) screen the user sees. However, these objects are not persistent. For example, if you rotate the device, the
Activity displaying your current screen gets destroyed and rebuilt, so the changed layout is properly recreated to fit the new screen dimensions.
The well known issue for a singleton is now that it must not hold a (static) reference to such a
Context, because that introduces a memory leak. There’s even a lint warning for that. So if you thought memory leaks weren’t a thing in Java, you, again, know nothing, Jon Snow.
There’s obvious ways around this, however. In my case I didn’t really need most of what was in the
Context anyways, so I just got what I needed and did not hold a reference to it at all. A good general discussion of the problem can be found here, for example.
The Real Issue (or “What the hell are you on about?”)
When reading up on that lint warning, I came across Stack Overflow, of course (because where else to go with this kind of stuff first? 😅). Two of the many relevant questions are here and here. The first one is not explicitly about Singletons, but leads to the second. Take a moment and read or at least skim the comments. Do it.
I want to especially point out the comments to this answer to the first question first. In case they get deleted:
to the guy bashing [emphasis added by me] the guy who bashed the example above: the point of this thread is the Lint warning in conflict with Google’s own recommended pattern of creating singleton
Read: “Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)” Do you know what context classes are? [emphasis added by me] Activity is one of them, and you should not store Activity as a static field, as you described yourself (or it will leak memory). However, you can store Context (as long as it is the application context) as a static field, since it outlives everything. (And thus ignore the warning). I’m sure we can agree upon this simple fact, right?
When I read that it was slightly off-putting. I may be influenced by the other question’s discussions (see below), but that almost sounds passive aggressive to me. Don’t get me wrong, I don’t want to be the party pooper here and play the SO police. It was just that for me as a third party interested to actually learn something that was just distracting and seemed uninformative.
The second question’s accepted answer didn’t look much better to me.
First off, the accepted answer there is plain dangerous. The proposed code compiles and in many cases it won’t mess up your app, but as the comments elaborate, it relies on several assumptions, namely that you don’t try to get this
Context object via a static method before it’s initialized (which may happen later). It also violates the recommended way to do it with a singleton that is also linked in the article I mentioned above. Granted, the documentation for Android isn’t very helpful, as a matter of fact there is even an example that is plain wrong: Here the singleton’s
getInstance() method relies on being called with the application
Context attained from
getApplicationContext() the first time. Otherwise, i.e. if called with e.g. an
Activity, you leak memory. That’s never a good design, as you need to know arbitrary conditions on how to call an otherwise innocent looking method. Other questions I won’t link drew that out of the hat and people argued that this was either the way to do it or how it shows you shouldn’t do singletons with any kind of reference to a
Context at all. Sigh…
Besides that, the tone of some of the comments on question number two didn’t seem constructive either, worse in fact when compared to the comments of the first question. Some got deleted by now it seems, so barely half of them make sense, only reducing trust in the answers further. To me, a lot of this read like “I am right!” – “No, I am right!” which doesn’t help you as a third party at all. Hell, there’s 43 comments (at the moment) on the accepted answer alone. And as said, that answer isn’t even the one that should be accepted, let alone have most upvotes.
And here, finally, after a thousand words, lies my point: Why the frickity-frack is that?
I am afraid, that the cliche of the socially inept developer has some merit. What such long comment wars, and a prematurely upvoted and accepted answer tell me is that a lot of people are unable to properly communicate tech stuff. I’m going out on a limb here, obviously, but my conclusion is not just driven by this specific example of bad Stack Overflow questions. To be fair, as I found out the documentation for Android is less than optimal here and the habit of just ignoring lint warnings is nothing new.
However, it appears that developers love to argue their point with a very direct, small, and most of all quickly chosen set of words. This is bound to offend someone with even a slightly different view on things. It omits assumptions that are important for understanding a question as well as an answer (not just on SO, in general). This includes assumptions not just about the technology at hand, but also about how the other might feel and understand one’s own arguments. And no, I am not saying we all should be overly politically correct best-buddies that wrap every person into a comfortable bubblewrap foil for fear of offending them. But if you just brusquely wise-ass someone you prematurely consider an idiot (or you give the impression you consider them as such), nothing will come of it!
Let me explain it in a different way: I often think a developer encountering an argument made by someone else that they don’t agree with automatically assumes the other person is an idiot:
“They must be wrong, right? After all the topic is tech, and a question about technology is either right or wrong. And since I know the right answer, the other dweeb must be wrong, right? Oh, and their emotions can’t play a role either, we’re talking cold, rational bits & bytes here after all. Plus I don’t even need to be that explicit, me pointing out their flaw must be sufficient, they can read up the rest in the manual!”
If then both parties think like this, the entire discussion quickly becomes moot. Which, ironically, means that we now have “tech talk” that’s not rational at all: It’s just a waste of time (in this case my time, an unsuspecting, innocent bystander who just wants to learn something… and that is clearly the greatest atrocity here! 😬) If you can only answer somebody’s question like this, maybe don’t answer at all.
The Bigger Picture & My Conclusion™
Unfortunately that’s not it. There’s a bigger risk here. If a good discussion about a complex topic is not provided, the quick and dirty solutions bubble to the top. People who are in search for a solution to a given problem in a lot of cases won’t bother reading through the arguments some “egomaniacs” (at least in the perception of those passers-by) throw at each other. They pick what just compiles, which is why we end with dangerous, potentially breaking stuff like in that accepted answer to the second question, as said.
Stack Overflow usually does a very good job of trying to counter that, but I think even the way this site works has its limits. Coming from iOS and encountering a much larger number of Android developers I got the impression there’s a lot of those “just make it compile” tips out there than is good for the platform. Sure, iOS has that, too, but my subjective impression was that it’s not as bad, and questionable answers rarely have that big impact (like over a thousand upvotes). Maybe a factor is also that Android may be easier accessible or more attractive (Apple hardware is more expensive and not as widely adopted), I don’t know. Regardless, the issue is more general to software developers of all areas, I’d say.
In the end, I guess there is no easy solution to this phenomenon, so I can only hope some people heed my concluding advice: Don’t be dicks. Be nice, even if you think the other person is wrong. Better write a decent explanation of your points than relying on the issue being “logical”. Be careful when insinuating incompetence, avoid it at all if possible. Conciseness is nice (and sure an area I can improve in), but from what I have seen, the longer documentation is usually the better one in most cases.