I have been making Android apps troughout my whole career, starting with coding on the android dev phone1, back in 2009. Meanwhile I have written 20+ apps for customers like Paypal, Nrc, Dutch Railways, Vodafone and the Red Cross. Did some presentations every now and then, wrote 100+ pages of android tutorials at androidworld.nl, won prices at places like Google and Accenture, got featured on television and in magazines, made my own orm, dynamic form generator and code hot swap libraries. I researched the java compilers, made a faster type inference and am working intensively on writing a lightning fast compiler, including incremental type checking & package building. So it would be fair to say I own a lot to the Android ecosystem. Fun, income, admiration, lessons learned and all other usual experiences you get during a developers journey. Unsurprisingly, I think Android is a good system.
However, despite of all that love, I have to say I miss something. Its hard to see, because, well, it’s about seeing. I miss Android having an architectural vision.
When developing Android apps, the pattern of writing Android apps more or less became clear to me;
- define your datamodel
- write/configure a few parsers to upload/download data from a remote server and store the data locally
- write some sql queries and sql parsers to load the data from your database into memory
- create a few controller methods that convert user input to local data changes and sent it to a remote server
- write tests for above (essential) methods
- create some xml views that can display the data that is loaded in memory
- tweak the ui a bit; set some styling and background-images on all layouts/buttons/textviews and maybe set some animations
And thats it. (almost) all Android apps fit in this seemingly simple approach. But a big problem is that when you go about each of those steps, there is an abundant number of ways you can implement them. Take data-sync for example. You could at least use one of the following approaches;
- use android’s syncadapter class (officially advised)
- use android’s asynctask class (officially not-advised)
- use alarmtriggers for scheduled syncs
- use reactive callbacks
It didnt took me long to write down this list, and there are even more other ‘justifyable’ approaches. I think this means that the suggested approach suggested by Google itself is simply not good. Because if it was, there wouldn’t be that much alternatives to choose from. Or from a different perspective; In all those years I have attended conferences and android meetups I can’t just not remember one single fellow developer ever recommending to me to use the syncadapter class (except google’s own developers). Or put differently; I myself really tried to use the syncadapter class, but I found its invocation to unpredictable, and its implementation too cumbersome. Internet suggest a lot of other alternatives, my fellow Android developers never recommended the syncadapter class, and I tried to use it, but neither I would suggest to use it. So when it comes down to implementing one of the cornerstones of every Android app, data-sync, there is just no official guideline to implement that is also actually effective. I think this is big problem. Because there are a few nasty caveats regarding data-sync; a lot of developers have to reinvent their own wheel, frequently causing a lot of complexity and bugs along the way. It is sadly no wonder that lot of play store apps suffer from data sync issues. And we are already 10 years down the road.
However, data-sync is not the only time-consuming feature of Android. What about another cornerstone of Android development, ui creation. When implementing a ui, you can choose between xmldatabinding&livedata&viewmodel vs uri updates & loadermanagers vs plain sqlitcursors vs observer&observable. Or what about using Fragments vs non-fragments vs custom views vs code generated layouts? Every junior (and medior) developer has to constantly think about what route to take, having to learn a certain approach, wasting valuable time, and also adding unnecessary complexity along the way. Or take the ‘jetpack’ library. Is it that much of an addition? To me they are primarily a collection of classes that work together in small subsets, encouraging already existing software design patterns through a new set of interfaces and abstract classes, and sometimes removing some boilerplate at the cost of adding some architectural dependencies. Or when you actually start to write code in Android, it is as if you are entering the code-jungle; why do I need to know 5 languages when I want to write a basic android app? I need to know groovy, sql, java, proguard, xml, and preferrably kotlin as well. Why wont they choose just one language, transform all other tools into that same language and stick to it.
Because of all these ambiguities and different languagambiguitieses, It takes quite some experience in coding Android once you can be reasonable sure that your architecture is sufficiently clean&simple. And it costs a lot of bugs, money and developer&user frustration.
Also, take the whole development&compilation process. It is just not efficient. Let’s have a look at it, starting by writing code, all the way down where the android device starts to execute the ones and zeros. It is processed in all of these steps;
- writing the actual sourcecode in an code editor (coding)
- collecting all necessary files in the build phase (building)
- transforming and linking all sourcecode into an intermediate format (compiling)
- obscuring all bytecode so that it is harde to reverse-engineer (obfuscation)
- loading the file on the android device (package manager/installer)
- pre-optimizing before actually executing the programing (jit)
- actually running the program (art).
- And when debugging your code, your code and your run-state is also represented in a format represented by the android debugging bridge(adb)
So the process of writing and executing code takes a whole lot of 8 different steps to complete. In each of these steps a new environment is used with its own format&specifications&rules, each with its own redundant import/read and export/write steps. So many different layers dealing with the same level of abstraction. It does not surprise me that compilation of android is extremely slow. And that android studio requires a lot of memory to run.
Performance-wise, we aren’t exactly in heaven either; Why do android apps still have a lot of ui-stuttering issues, especially with listviews? arent we supposed to have smartphones that are 4 times faster than 10 years ago? what is happening with all the added cpu power? Are developers incrementally&repeatedly wasting all those hard-earder cpu resources every year?
Summing up; I think architecture&library-wise there is too much to choose from, which just causes too much complexity. When coding in Android, there are simply too much languages you must know. When actually building your code it is processed through too much similar abstraction layers resulting in long build times, spending precious developer time. And performance wise I just dont understand why there are still a lot of ui-stuttering issues, and why the same kind of bugs (e.g. data-sync) keep popping up in different apps in the playstore.
Why do I think that Android as gone astray? I think the biggest cause is that there is just no single simple vision. The language ecosystems reactively keep on stacking ‘libraries’ and adding ‘tools’ upon eachother that seem useful at any random moment. In this way all functionality becomes trapped in silos of different languages and subframeworks, encouraging architectural isolation and thus eliminating any opportunies for streamlined architectural conventions that span large part of an eco system. It prevents the evolution for a gut feeling, a common convention-based sense of approaching architectural decisions. There is no simple ‘android-way’ of doing things. Well it exists, but it is complex and it is ambiguous. A related cause is that android developers love to make libraries. I think almost every android developer at some level senses that there are quite some architectural gaps in android and tries to fill some of them. However, there is no a set of architectural grand-design conventions about how to go about coding android. So almost all new libraries are not solutions to this architectureal chaos, but merely solutions to a few of its many sympoms, and frequently adding to the architectural chaos as well.
So what to do about this?
On a framework/library level; I’d say try to ignore these so called new ‘libraries’ as much as possible. The apps that need to be written today aren’t that much different from the apps that needed to be written five years ago. Writing simple&efficient code was perfectly possible back then, and still is. Of course it makes sense to use Room instead of Ormlite, to use retrofit/httpok instead of the plain http java classes, but that’s about it. For the rest you can still write beautiful simple code with classsic patterns like observer/observable, cursorloadermanagers, uri updates and separate android services that do your rest communication and afterwards send a uri update to you activities. Or if the Android team really wanted to fix the Android ecosystem; I suggest they make a convention-heavy automation framework, that only needs a few dozen configuration lines, and handles all your database crud and http get/put/post/delete sync actions so that the only thing you’ll be doing is displaying your data in your activities, and writing some bussiness layer logic (in this way there ll be even time left for optimizing the ui). Now if they got their heads wrapped around thoses issues, using stuff like viewmodels actually does make sense. But don’t make a few interfaces and abstract classes, brand them as a ‘jetpack’, throw it at your developers and hope they magically ‘lift off’ their development skills. If you actually want to help your developers, make a steady framework for them that actually takes work out of their hands. These kind of frameworks require some thinking, but once you figure it out, it shouldnt be that hard.
Performance wise; the threading management of android is horrible, and I think its a pity that android apps keep on stuttering while scrolling or rendering some animations. We are currently having phones that are more powerful than a playstation3/xbox360. So it seems its perfectly possible to run fancy computer games with all kinds of graphics shaders, but it is impossible to find a way to smoothly animate one single scrolling list…. Google should upgrade the threading in the art (android runtime), add a bunch of classes&interfaces that once you use those, you are guaranteed for smooth scrolling performance. It shouldnt be that hard for loading images. Once, for a client I went through so much work for a smooth ui that he ended up saying ‘that’s a smooth app, it reminds me of an iPhone’. Do you feel my pain?
On a coding level; Android should lessen its language dependencies. It’s a mess. Either choose groovy, or choose java, or choose kotlin. And ditch the rest for good. Its even relatively straightforward to change layout declaration, styles, androidmanifest, dynamic drawables and proguardconfig to one of these languages as well. It’ll be so much more simple.
Is this too much to ask? I don’t think so. But someone at Google should need to stand up for this, collect a team of terrific framework engineers and fix this. Gl hf <3