Let me tell you about the good, the bad, and the ugly in the native Android development world.

In 2013 I quit my job as a java server-side programmer to start studying Android at home. Then, I got my first Android job and I have worked in several companies since then. At first I was thrilled to be able to show my apps to friends & family. To run them, I didn’t need a huge Oracle database or a server with a JVM . Devices were slow, yes, but not needing that heavy infrastructure and being able to recycle my java knowledge for mobile programming was amazing (let alone the cost of it: Free!).

The Android platform

Since the beginning, I liked switching to the new platform and learning new things about activities, asynchronous programming, push notifications and concurrency. Then, Honeycomb arrived with fragments; and then, Ice Cream Sandwich with Holo. People where having a lot of fun writing code for small apps.

As applications grew, devs started to think about cleaner code, better architectures, better tools and testing. They realized that those huge activity classes would backfire one day and they reused classic programming patterns and came up with new ones. Everybody started talking about MVP, MVVM, hexagonal architecture and open source libraries where thriving. I was excited reading all those posts by fellow programmers, and watching those great talks.

The Android platform was designed to be very versatile. Actually, I think that’s its greatest quality and that’s why it works on so many phones, tablets, TVs, watches, cars and things. It was thought to be scalable, always being aware of hardware constraints like CPU speed, memory and battery. Android’s layered architecture allows separating concerns for different technologies and teams working on them. Thanks to this, for example, Google was able to seamlessly switch to OpenJDK in Android Nougat:

Something feels wrong

I think Android is a great platform, but I also think that some APIs available to developers in the framework layer (the green one in the previous image) really should be redesigned.

Activities are arguably the most important component in Android, and along with fragments, they are hard to grasp and to be used correctly — and Google knows it. Their lifecycle is intricate, and this only adds complexity and confusion to the developer:

Having so many callbacks makes it difficult to do composition over inheritance. That’s why inheritance is overused for activities/fragments in most apps. It would be great to have more fluent ways of writing code.

One of the most annoying things is the effort it takes to properly implement handling runtime changes to, for instance, rotate the device — which is something fairly frequent; One of the goals of activities is to stay always in the state where you left them. For this purpose we use onRetainCustomNonConfigurationInstance(), onSaveInstanceState(), retained fragments, headless fragments…… and still saving/restoring activity/fragment state in a highly concurrent environment is hard.

And that’s not all: Anyone trying to visualize the contents of a SQLite database? Fortunately Facebook built Stetho. Who hasn’t dealt with undocumented behaviors in the webview? App build times over 5–10 minutes? Has anyone heard about fragmentation? Java 8? Do you like the new permissions model in Marshmallow? Nice animations are only available on KitKat-Lollipop and later. Animated SVGs are a great feature, but they’re so laborious (I’m keeping an eye on this cool tool). Who hasn’t had problems with viewpagers? Anyone likes debugging the FragmentManager? ViewTreeObserver hacks? I wish CSS was used for styling and animations, or at least if Google had created flexbox for Android sooner…

Creative solutions to skip the Andriod UI problems are: Mortar and Flow, react native, nucleus, Mosby… but they all feel like squaring the circle.

The Android UI system works well and it’s very performant but it might be the worst part of the framework for developers. And on top of that, everything you learn on building Android UIs will not be reused for any other platform.

Testing

I have written before about testing in Android, trying to share what I learnt. It is not easy to write testable code in Android compared to other platforms or tech stacks, and it is necessary to invest a lot of time in having a good architecture in order to write testable code. Robolectric and gradle unit tests are your best options for small, quick and reliable unit tests on your JVM. For the rest, you might need to write instrumentation tests, which have always been slow, and difficult to keep simple and hermetic.

How are you supposed to write a small test for content loaders or sync adapters? You will end up with flaky and slow end-to-end tests. And I can tell you by experience that having flaky tests is very annoying: every time your team gets a failure email from your CI server you’ll have to go back and see what’s wrong.

After spending long and frustrating hours trying to write better tests in Android, I must say that this area is improving. Espresso made things much easier for instrumented tests — still some flakiness, weird behaviors in webviews and dealing with idling resources for background threads makes it hard. Google is improving testing documentation with examples, and codelabs. Being able to write unit tests on the local JVM has been a huge improvement.