As 2020 comes to an end, it’s time to take a look at what’s going on in Android development ecosystem. Therefore, in this article, I’ll summarize my opinions, gut feelings and predictions for the future.
Review of Last Year’s Predictions
As you might remember, last year I wrote a similar post. I didn’t remember what I wrote in that article at all, so it was interesting to read it now and see how accurate my predictions turned out to be. Allow me to reflect on them.
However, this past year has been absolutely crazy even by Android ecosystem standards. Stuff got added, stuff got deprecated or removed, docs changed, new official guidelines were introduced, etc. When I come to think about it, I can’t draw a complete, detailed picture of Android development landscape in my mind anymore.
The pace of change in Android ecosystem hasn’t slowed down in the least. If anything, it became faster.
All in all, I’d say that new Android apps should definitely use AndroidX artifacts. I’d also recommend to plan for migration to AndroidX in existing project, even if you can’t see clear benefits right now.
The part about AndroidX (which is a synonym for Jetpack) was correct. Not using these artifacts today is crazy (unless you’re pinned down by a huge legacy codebase, or some other major obstacle).
Sometimes background work requirement will be unavoidable, but in most cases you can do without it. It might be the optimal choice, even if at the cost of some inconvenience to users.
Background work is still a shitshow according to the latest comments on this issue (which is still marked as P3 and S3), so this recommendation is as relevant today as it was a year ago.
Therefore, as Kotlin adoption rates increase, I expect the adoption of SQLDelight to increase as well.
I don’t have any numbers to analyze the adoption rate of SQLDelight, but it looks like this prediction was accurate. At the very least, that’s the database recommended by the official Kotlin Mutliplatform (KMP) docs today.
It’s nothing to worry about right now, but looks like in the longer term SharedPreferences will be deprecated in favor of this new approach.
New Jetpack library that I had mentioned last year which is aimed to replace SharedPreferences was released. It’s called DataStore. My recommendation not to worry about it in 2020 was absolutely correct. However, if it gets out of “alpha” in 2021, I think it might be something to look into next year.
[…] Koin is written in Kotlin, so it enjoyed a bit of a ride on Kotlin’s hype waive. This wave is pretty much died by now, so the excitement around Koin will probably decrease going forward.
In the domain of dependency injection, I predicted that Koin won’t get much traction. I don’t have any quantitative data in this context, but looks like this prediction was fairly accurate.
Therefore, despite the fact that Dagger indeed provides very nice set of features to make DI simpler (once you know how to use it, of course), I believe that we’ll see a growing interest in Pure Dependency Injection.
This prediction about the rise of Pure Dependency Injection was absolutely incorrect.
In my estimation, once ViewBinding will mature and become widely adopted, DataBinding will fall in popularity even more and become “legacy” framework.
DataBinding is dead for all practical purposes. Anyone adopting this framework for new projects does a great disservice to their long-term maintainability.
Therefore, if Google indeed has ulterior motives and wants to force all projects to use ViewModel, they’ll need to deprecate
onSaveInstanceState(Bundle)as well. This sounds crazy, I know, but it’s actually good because if such crazy prediction will come true, you’ll know that the underlying theory was correct.
Luckily, so far, the theory about Google deprecating
onSaveInstanceState callbacks hasn’t materialized yet. Let’s hope it’ll remain this way going forward.
Another popular framework for multithreading in Android, RxJava, quickly becomes “legacy”
RxJava is pretty much dead. Last year this prediction was still “controversial”, but today it’s clear that it was spot on.
All in all, I’m pleased with the accuracy of my past analysis. Now let’s see what happens in Android ecosystem today.
As some of you probably know, I’m not a fan of Kotlin in Android, to say the least. Not because it’s a bad language, but because its adoption caused a lot of churn. However, I’ve just realized that I’m still surprised by the relatively slow adoption rate of Kotlin in the ecosystem.
See, my gut feeling tells me that in 2020 Kotlin just crossed the 50% mark, meaning that maybe just a bit over 50% of Android code is written in Kotlin today. This is consistent with Google’s claim that “more than 60% of professional Android developers use Kotlin” (which doesn’t mean that they use Kotlin exclusively, of course). Now, gaining 50% of a “market share” in 3-4 years is an achievement for a new programming language, but only if it competes on merit. That’s not the case here because Google simply forces Kotlin down our throats. From heavy marketing campaigns and ridiculous initiatives like the recent MADscore plugin, to adopting Kotlin for new libraries – Google promotes Kotlin much more heavily than even JetBrains does. Given all this pressure, it’s surprising that Kotlin doesn’t enjoy much wider adoption.
On the practical side, if you look at the big picture that includes the entire ecosystem, Kotlin is still inferior to Java in Android. I guess many Kotlin fans will find this statement outrageous, but that’s hardly surprising. They had already been enraged three years ago, when I shared my initial analysis of Kotlin’s effects on development productivity. Surprisingly, my arguments from that article are still valid, but now I can also support them with factual Kotlin’s drawbacks (three years later!).
First of all, compilation of Kotlin code is still horribly slow compared to Java. Kotlin’s auto-complete is amazingly inferior in terms of both accuracy and responsiveness (that’s probably the biggest productivity killer for me). Then you have constant Kotlin-related lags and other performance issues in Android Studio (the most annoying one is probably slow syntax highlight). Some important IDE features haven’t been supported for a long time in Kotlin projects (like this basic refactoring) and I guess there are others which aren’t supported still. That’s what I remember from the top of my head, but I guess the complete list of drawbacks and limitations is much longer.
Your mileage may vary, of course, but I feel more productive writing Java code in Android. Yes, I need to write more of it, but at least I don’t stumble each time auto-complete does the wrong thing.
However, said all that, I wouldn’t start a new Android project in 2021 using Java (unless I’d have a good reason to). Not because Kotlin is better, but because it surpassed the 50% mark and because Google will keep forcing it on us. As for existing Java projects, whether to introduce Kotlin into them is still a nuanced question which should be decided on case-by-case basis.
Undoubtedly, Jetpack Compose is going to be the biggest addition to Android toolbox in the coming year (maybe even ever).
Now, despite the fact that it’s currently in alpha, it already draws a lot of community’s attention. The most amazing thing about Compose is that many developers claim that it will make everything so much better and solve so many problems. I’m sorry to be the party pooper, but adoption of Compose will be long, painful and very expensive process. As usual, early adopters will waste enormous amount of time discovering, reporting and working around bugs, all the while telling everyone around how productive Compose is. That’s just how these things work. Will it become better eventually? No one can tell that for sure at this point, but, given how bad Android’s UI toolkit is, that’s not a very high bar.
As I predicted three years ago, Compose is going to be a cross-platform framework. Yes, I made this prediction even before we heard the name “Compose” for the first time. Today we know that Google prepares it for Android and JetBrains already released the first version of Compose for desktop. We don’t know about other targets yet, but I assure you that, at the very least, Compose will eventually also support iOS and Fuchsia (if Fuchsia will “launch”).
I haven’t tried Compose yet, but I do plan to see what’s going on there in the coming months. That said, if you really care about productivity, stability and quality, I can already recommend avoiding spending much time on Compose in the coming year. You’ll hear many developers, bloggers and speakers claim that “if you don’t embrace Compose, you’ll be left behind”, but that’s also what people said about Kotlin three years ago. In practice, you could’ve been happily coding in Java all this time (sparing yourself a lot of headache), and you can even keep coding in Java if that’s what you want. The same will happen with Compose, at least until it matures, supports both Android and iOS, and Kotlin mutliplatform adoption increases.
If you’re a blogger or a conference speaker, on the other hand, the hype around Compose is going to be huge, so it’s an opportunity.
Google promised “stable” release of Jetpack Compose some time in 2021.
While most Android developers see Jetpack Compose as a “better way to build UI on Android”, I believe that’s just the current marketing message by Google that serves their interests. In my estimation, the only reason Jetpack Compose exists is to support cross-platform UI. That’s not some kind of aferthought, but the foundation on which a decision to launch Compose project was grounded. In many aspects, Compose is “Flutter’s UI in Kotlin”.
However, the above statement immediately leads to a very interesting question: why would Google invest that much resources into Compose, given Android apps aren’t cross-platfrom? Has Google become altruistic lately and wants to open Android ecosystem to external players? The answer is no. The full discussion of this aspect would bring us back to the series of posts that I wrote three years ago about the future of Android, but I don’t want to repeat my theories here.
The bottom line is that I believe that development of Jetpack Compose was synchronized with Google’s investment into Kotlin Multiplatform. Many developers believe that KMP is JetBrain’s project and Google has nothing to do with it, but that’s just what Google would like you to think right now. In practice, KMP and Jetpack will gradually evolve into a single ecosystem maintained, jointly, by JetBrains and Google.
In 2020, we started to see the first signs of KMP and Jetpack convergence. The most prominent one was the fact that it’s JetBrains who ports Compose to desktop, but there are additional signs as well. Therefore, if Compose indeed hits stable in 2021, I’m fairly confident that we’ll see a major push towards KMP from Google’s side.
As far as I understand, Kotlin Flow is basically an alternative to RxJava in Kotlin. Sure, some implementation details are different, but the general idea is the same. As you might know, I wasn’t a fan of RxJava, to say the least. Long ago, I predicted its demise and recommended staying away from this framework. However, I still can’t make up my mind about Flow.
On the one hand, since it’s analogous to RxJava, it’s also a library with a very steep learning curve that provides very questionable benefits. The benefits are even smaller than RxJava’s because Kotlin has Coroutines, which, among other things, already replace RxJava’s Single, Maybe and Completable types. I also feel that Flow is more complex than RxJava (in combination with Coroutines), so that’s a bad sign.
However, on the other hand, Flow is an official framework by JetBrains. In some sense, it’s part of Kotlin. Therefore, I expect it to enjoy a more widespread adoption than RxJava. In addition, Google started to adopt Flow for some Jetpack APIs and I expect this process to continue going forward. In fact, looks like Google is going to effectively deprecate LiveData in favor of the new SharedFlow and StateFlow constructs (they can’t fully deprecate it yet because Flow only works in Kotlin). Luckily, I wasn’t a fan of LiveData either, so I don’t care about this change too much. I guess it will increase the adoption of Flow framework in the long term.
I don’t see myself using Flow in professional projects in 2021, but I will keep an eye on it. Well, unless I decide that it’s a waste, in which case I’ll surely let you know about that (btw, don’t forget to subscribe to email notifications).
In the department of dependency injection, Google released Hilt. Even though I don’t see much value in this framework for myself, it’s relieving that Google finally admitted that they screwed up with
dagger.android and effectively deprecated it.
In its current form, Hilt is just Dagger with a set of additional conventions. However, I suspect it’ll evolve to become a more interesting tool in the future. If you haven’t looked into Hilt yet, you can read my article about it.
Should you use Hilt in your project? That’s a nuanced question.
If, for example, you took my Dagger course and already architected your app according to my recommendations, there is almost nothing you can get out of Hilt (except for more risk due to immaturity and additional annotation processors). On the other hand, if you listened to Google’s recommendations two years ago and adopted
dagger.android, I think it’s worth assessing the long-term ROI of migration to either “standard” Dagger, or Hilt.
Long time ago, there was just
findViewById() method. It was ugly as hell because it required casting of the returned value. However, you could remove this limitation with a simple custom helper method that used Java’s generic type inference. At some point, this workaround made it into Android framework itself, so the pain was alleviated globally.
Then there was Butterknife library and “cool” developers used it for a while.
Then Google rolled out the disgusting DataBinding, and “cool” developers started to use that.
Then Kotlin came along and we got Kotlin synthetics. Guess what “cool” developers did…
Then we were told that all the previous approaches weren’t good and Google released ViewBinding library.
In late 2019, I was curious about ViewBinding and thought that I might give it a try. However, after its release (and still to this day), I heard developers complain about various problems and edge cases. Therefore, unfortunately, I had to conclude that it’s just one additional unfortunate attempt at “solving” a problem which wasn’t really a problem to begin with.
Meanwhile, while all these “cool” approaches came and went, I just used
findViewById() and recommended everyone to do the same. Happy to report exactly 0 issues with this approach over the course of the last 6 years. Cumulative time spent on learning and debugging: on the order of one hour.
In addition, given Google’s enormous investment into Jetpack Compose, any effort spent on learning or migrating to ViewBinding is just flogging the dead horse in my opinion.
I’ve been using the humble FragNav library for navigation inside Android apps for the past two-three years. It’s just amazing. Everything about this library is so simple and elegant. Almost never felt like I need anything else. Therefore, the moment I saw the API and the functionality of Navigation Component, I immediately decided to avoid it. In my opinion, it’s just a monstrously over-engineered and poorly designed framework.
Recently I started a new pet project and decided to give some “new and shiny” tools a try, including Navigation Component. After implementing bottom tabs navigation using this library, I can say that it’s probably the worst navigation framework I’ve ever seen.
Said all that, for a very long time I was convinced that Google rolled out Navigation Component to prepare the ground for seamless transition to Jetpack Compose in the future. I thought that at some point they’ll add support for Composable navigation targets, so for projects which use Navigation Component, transition to Compose will be simpler. However, even this doesn’t seem to be the case because navigation solution for Compose comes as a standalone library with a very different API.
All in all, I’m really puzzled by Navigation Component. Clearly, a lot of effort went into it, but it’s not clear why we needed this addition to begin with.
In-App Review API
This year Google shipped a new API which allows developers to do the thing that we always wanted to do: collect users’ feedback right inside the application. Now you can ask your users to rate the app without redirecting them to Google Play, thus reducing the friction by a lot.
According to what I read on the internet, looks like you can greatly increase the number of ratings your app gets with this API, without negatively impacting the average. This is a big win because I’m fairly confident that Google uses the number of ratings as one of the ranking factors for ASO and potential users also factor this metric into their decision of whether to install your app, or not.
So, if you’ve got an app on Play Store and haven’t tested in-app reviews yet, I definitely recommend investing a bit of time into that.
Android in Cars
Some models of cars provided support and integration with Android devices for years, and there were also “specialized aftermarket car tablets” which you could install manually into your car. Recently, Google announced at least two new initiatives.
The first one is Android Automotive OS. It’s basically a specialized version of Android platform that third-party car manufacturers can modify and then use as an in-vehicle infotainment system. As far as I understand, this OS is very new and hasn’t been widely adopted yet.
The second initiative is Android for Cars apps library. As far as I understand, that’s just a selection of applications optimized for Android Auto. Now, Android Auto is not the aforementioned Android Automotive OS. It’s just a special feature which allows Android devices to integrate with supported third-party in-vehicle infotainment system. In some sense, Android Auto allows you to project the screen of an Android device onto in-car’s display. So, now Google decided to maintain a separate catalog of apps optimized for this mode of operation (these apps can also access some additional APIs).
All in all, there is not much I can say about any of these initiatives right now, but there is no doubt in my mind that the market for in-car applications is going to be huge. That’s not to say that Android will become a major player there, though. Android Things fiasco was a hard lesson to learn for many developers. However, like any new promising niche, Android inside cars can turn out to be a huge success in 2-3 years.
In 2020, Google clearly made a big step in automotive direction with Android and I expect to see more news in this context in 2021.
So, these are my main takeaways from 2020 and main predictions for the coming year. I know that some of them sound controversial or flat-out crazy, but, at this point, I have a long track record of crazy predictions that turned out to be accurate.
All in all, 2020 feels a bit wasted in the context of Android development. There was a lot of activity, but, except for “product” level stuff like in-app reviews, nothing of importance changed for the better. Most of what happened feels as a waste. I really don’t envy developers who join Android ecosystem today because it looks like they’ll need to re-learn everything in the coming 1-2 years.
At a very high level, it feels like Android framework team at Google desperately chases Flutter’s evolution and tries to pivot Android to cross-platform “on the fly”. However, they aren’t open with us and attempt to manipulate developers, for some obscure reason. Really, why all this secrecy? If they’d tell openly three years ago “we are going cross-platform, so it will take a while”, I’d probably be more OK with that. In addition, if I’m right, and we’re indeed heading in that direction, why they keep making so many irrelevant changes?
I feel sad to say that, but I suspect that Flutter, as a framework, will be more stable and mature in 2021 than Android. Hopefully, I’m wrong.
Good luck to all of us and Happy New Year!