The Android SDK is the Worst Thing on Earth
Warning: severe rant ahead. Future articles will focus on providing helpful tutorials that solve problems. This one, not so much.
The Android SDK is really the worst thing on Earth. It’s absolutely horrifying.
In my twenty five years of professional development experience, I’ve never experienced anything like the Living Hell that is developing for Android. It is by leaps and bounds, the very last thing I would recommend any developer learn.
The day I started learning Android was the day I started drafting a new book entitled Android Gotchas. But since then, my understanding has deepened and with it, my disdain for this worst SDK in history. Android Gotchas is not enough. Someone needs to tell the truth about this pig. Loudly.
What will follow in the days to come is a nearly endless rant of things that suck about Android. But rather than simply shouting at the wind, I’ll make every effort to explain why a given thing sucks, how it could be improved and while we’re waiting for that magical day that will never come (where Google finally crafts a modern mobile OS and framework), how a given problem can be “solved”.
But first and foremost, Android sucks because:
The Android SDK is completely devoid of fundamental abstractions and encapsulation.
Fundamental Abstractions
Android lacks the fundamental abstractions every developer expects.
This is best illustrated with a simple metaphorical story. It starts with an innocent developer who decides:
I want some ice cream.
That’s nice. You want some ice cream. Everybody wants some ice cream from time to time, right? The desire for ice cream could even be considered fundamental. So let’s ask the Android SDK for some ice cream. The SDK responds with:
Give me directions to the nearest forest.
WTF? What the HELL kind of response is this? I have no idea where the nearest forest is. But more importantly, I don’t care. So, it’s off to Medium or Stack Overflow or ChatGPT, your new best friends, to try to figure out what just happened.
Turns out, the Android SDK does not simply produce some ice cream for you, despite the fact that ice cream is a fundamental need. The SDK needs directions to the nearest forest, so that when you arrive, it can ask you:
What kind of tree should I cut down?
What? What is this? I don’t want trees, I want ice cream! So now, you begin flailing about:
I dunno…Birch?
Android responds with:
Cutting down Birch tree. What is your preferred thickness of rubber?
Welcome to Android Hell. Hours wasted researching things you care nothing about, and you finally begin to realize what’s really happening:
What diameter tire should I produce from the rubber?
How many tires on your new vehicle?
Directions to nearest store that sells ice cream?
Frozen foods isle number?
Ice cream brand?
You poor fool. This is how your entire development experience is going to look in Android. Every time you expect the SDK to deliver something, even if it’s clearly a fundamental need, you’re going to get the most ridiculous runaround imaginable.
Encapsulation
In order to use nearly ANY class or module in the SDK, you’ll be required to know EVERYTHING about its inner workings. Encapsulation be damned. Black-boxing be damned. Intuition be damned.
I’m sorry about all of this.
My (least) favorite example of this is displaying a simple list. If you want to display a list (CLEARLY a fundamental need), you’re going to need to learn everything about the following classes:
RecyclerView — what it is, what it does, what its callback methods are named, the arguments its callback method receives, the return type expected by every callback, how to produce an instance of the return type, etc.
RecyclerView.ViewHolder — what it is, what it does, what its callback methods are named, the arguments its callback method receives, the return type expected by every callback, how to produce an instance of the return type, etc.
In addition, you’ll also need to write a minimum of two new classes which extend the classes above and a separate XML file defining the layout for each individual list item.
Put another way, to create a list of items in Android, you can expect to write 200+ lines of code in 2 different languages in 7 different files in 4 different directories using 5 different APIs.
Is that even legal?
This ain’t right, folks.
Context — Your New Ball & Chain
Context
is another perfect example of Android’s lack of fundamental abstractions and encapsulation. Put simply, Context
is an object containing metadata describing the current application environment. The majority of the Android SDK components need access to Context
in order to function properly. Makes sense, right?
The problem is, Android is fully incapable of inspecting its own environment and thus will require you, lowly mobile app developer, to constantly manually refresh its understanding of its own environment by manually obtaining and injecting a Context
into nearly every SDK method you call.
This is almost indescribably stupid.
Having to obtain and inject Context
all over the place is a tremendous pain. It absolutely kills code readability, brevity and clarity. And all the extra work you’re forced to do is aggravated by the fact that just obtaining Context
is often its own exercise in bewilderment. By my count, there are at least seven different ways to obtain Context
. Not one way, seven ways. Which way works? Only one of them, depending on the context in which you are trying to obtain Context
.
But, in true Android style, it gets even worse. The Android SDK will require Context
to be obtained and injected into methods that have no logical use for context, whatsoever. For example, consider the following:
- Under what context would the color blue become some other color, like purple?
- Under what context would the word interesting become some other word, like potato or gerbil?
- Under what context would a checkbox icon become some other icon, like a poop icon?
The obvious answer to each of the above questions is: Under no context, ever.
Yet, if you ask the Android SDK for the color blue, it’s going to demand a Context
argument, so it can figure out what the color blue is. And if you ask the SDK for the string interesting, it’s going to demand a Context
before it can safely return the word. And if you ask it to load a checkbox icon, it’s going to demand a Context
first. All this Context
, all over your code, doing absolutely nothing you care about, ever.
This is your new Android life.
The Android SDK is QUITE buggy
The Android SDK is littered with deeply insidious bugs that are guaranteed to suck precious time and energy from your soul. As a busy developer, I can accept ONE of the following conditions:
- An insanely deep learning curve, but rock-solid output.
- A shallow, approachable learning curve with a few bugs to be aware of.
What I cannot abide is an insanely deep learning curve with nasty little bugs or big, senseless breaking changes lurking around every corner.
Here’s a tasty little bug I uncovered just this week:
Two-way data-binding fails for any property named
is_{x}
.The bug above effectively means that if you want to use two-way data-binding in Android, your database tables cannot have columns called:
is_enabled
,is_complete
, etc. Instead, you must either rename the columnsenabled
,complete
, etc. or forego two-way data-binding. Or (get this) your project will fail to compile with this beauty of a useless error message:cannot generate view binders
.
Here’s another one, to file under General Android Madness:
MenuItem
(s) using customactionLayout
, are not reallyMenuItem
(s) AT ALL any more.Mentioned NOWHERE in android documentation is that if you choose to use a custom
actionLayout
for yourMenuItem
, the following absurdities ensue:1) App themes and styles targeting
MenuItem
are completely ignored
2) The menu item no longer responds to clicks, requiring you to manually assign click listener in `onPrepareOptionsMenu`
3) The menu item no longer responds to settingIsEnabled
. Of course, you can still setIsEnabled
. It will just be completely ignored. WTF?Thus, it’s painfully obvious that custom menu items are NOTHING LIKE
MenuItem
(s) at all. They probably shouldn’t be calledMenuItem
(s) then!
It’s hard enough trying to reason about the SDK without also having to battle the continuous infestation of insidious bugs and utter nonsense like the examples above. But be prepared, the infestation is real. And thus, your suffering will be as well.
Breaking Changes
The latest and perhaps greatest disappointment with the Android SDK is the landslide of breaking changes every Android developer is now forced to contend with on nearly a daily basis.
A perfect example of this is capturing a tap on the device’s back button. For well over a decade, we used the dead simple onBackPressed()
event listener. Then suddenly, and for reasons only the Android team cares about, onBackPressed()
was deprecated. Never mind why, we were instructed to change all calls to onBackPressed()
for a new and “improved” API: getOnBackInvokedDispatcher()
. Note the nearly comical renaming from a good name to a TERRIBLE name.
Update: Woke up this morning to discover that ALL of our Android 13 devices now crash on startup because Android has decided to break this API for a second time. And NOW, we’re expected to implement onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
in onCreate
. Reading the documentation for handling the ‘new new’ back button listener is an exercise in abject insanity. There are some 16 different ‘upgrade path’ combinations, each as indecipherable as the next, for how you should implement a simple back button listener, depending on what versions of Android you support, what you originally intended to do with the back button, etc.
Here again, an absolutely HORRIFIC breaking change, silently introduced, that forces EVERY Android developer on Earth to do work to satisfy what amounts to nothing more than the Android team’s internal needs.
Another example: As of SDK 34, the Android team has decided to deprecate overridePendingTransition()
, which has worked perfectly for decades. The new replacement method you are expected to call is overrideActivityTransition
. Naturally, this has to also be a breaking change, as overrideActivityTransition
now demands a new first argument called override Type
. Behold this ridiculous requirement for calculating overrideType
:
If we want to customize the opening transition when launching Activity
B which gets started from Activity A, we should call this method inside
B's onCreate with overrideType = OVERRIDE_TRANSITION_OPEN because the
Activity B will on top of the task. And if we want to customize the
closing transition when finishing Activity B and back to Activity A,
since B is still is above A, we should call this method in Activity
B with overrideType = OVERRIDE_TRANSITION_CLOSE.
Dear Android team: It’s not my job to go calculate and inform you what the overrideType
is every time I want a transition animation. The framework should do this calculation silently and automatically and get the hell out of my way.
So here’s yet ANOTHER breaking change that offers no discernable benefit, while imposing additional mental overhead on EVERY developer.
Another example: Woke up this morning to discover my MainActivity
was marked in error by the IDE. ALL 2093 lines of code in my MainActivity
were marked as errored. I thought “This is clearly a mistake”, so I tried restarting Android Studio. On restart, everything changed, for no reason at all. Instead of 2093 errors, I had 5 errors:
private val vm: MainActivityViewModel by viewModels()
private val registerVm: RegisterViewModel by viewModels()
private val inboxVm: InboxActivityViewModel by viewModels()
private val patientLookupVm: PatientLookupViewModel by viewModels()
private val imagesVm: ImagesViewModel by viewModels()
Suddenly, the by viewModels()
code, which has worked perfectly without incident or adjustment for years, was meaningless to Android Studio and in error.
Tried to Invalidate Caches and Restart and it worked. All 2093 errors, then 5 errors, were resolved. There goes that 15 minutes of terror. And for no reason whatsoever.
And it’s getting worse and worse. More and more breaking changes are introduced by the Android team with each new release, forcing developers into a kind of morbid psychotic codependency with the SDK.
The Android SDK is not a framework
The entire methodology for usage of the SDK has confused and bewildered me for years. I should never be forced to subclass a component in order to use it. And I should never be forced to learn the finest details of the inner workings of a class in order to use it.
What much of this boils down to is this: The Android SDK is not a framework. It looks like a framework. It smells like a framework. It’s documented like a framework. It’s promoted like a framework. It’s taught like a framework. It’s described like a framework. But it is not a framework.
The Android SDK is a bare-metal layer of Java code sitting atop the Android OS. It provides you with exactly ZERO of the fundamental abstractions you naturally expect from any SDK, requiring you to reinvent the wheel every time you want to accomplish even the most obviously fundamental mobile task.
Here’s the hard truth:
The Android Framework you’re looking for doesn’t exist. Rather, it must be built by you, by hand.
The good news is that once you’ve learned every square inch of the SDK’s inner workings and you’ve crafted up your very own framework that properly abstracts and encapsulates such fundamental needs as:
- HTTP requests
- Database
- Windows & Dialogs
- Toolbars
- Lists
- Forms & Validation
- Images
- Text
- Colors
- etc. x Infinity
then, and only then, your development speed will quicken and you’ll be able to write mobile apps for Android with clarity and efficiency.
Conclusion
Lest it not be obvious to you by now, I’m no fan of the Android SDK. In fact, I think it’s just about the worst thing ever, a nearly criminally awful soul-crushing, time-sucking waste. It pains me to consider the sheer number of precious hours I’ve wasted scouring the interwebs, searching for ways to accomplish the most fundamental things, such as:
Styling a Spinner using Material Design
etc.
There’s not much I can do to ease the inevitable pain you will experience as an Android developer, especially if you’re a developer who already has experience with other languages and proper frameworks.
Perhaps the biggest piece of advice I can give you is to be patient and persistent. The one saving grace of Android is that literally millions of other developers have shared your pain and thus, you’re likely only a google search or two away from finding the shockingly complex answer to your easy question. Be prepared to have your development flow interrupted on a nearly continuous basis: type a few characters, get confused, google search. Lather, rinse repeat, ad infinitum. If this type of workflow sounds like fun to you, you’ll enjoy Android development. If not, oh well, I guess “Suck it up, buttercup!”
Most importantly, understand that the Android SDK isn’t like other frameworks because it’s not a framework at all. It doesn’t concern itself with providing the things frameworks do — namely, fundamental abstractions and encapsulation.
Google, if you’re listening, the world needs a proper Android framework. We’ve needed it for years. If you REALLY want to do the world a favor, it’s time to craft a new mobile operating system that makes a proper framework possible, because the SDK is a crime against humanity.
Best of luck!