The ecosystem of native Android development is very dynamic. Well, at least I experienced it as such for the past five years, while I’ve been heavily involved in all things Android. During this period, Google released new sets of recommendations, libraries and frameworks every 2-3 years, and I invested much time to review these changes and sort out the sheep from the goats. I’m sure that many Android developers can relate to this experience.
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.
Therefore, I decided to set some time aside for a research and then write this post. That’s my attempt to summarize what’s going on in Android ecosystem and make some predictions about the future of native development. I will structure my thoughts into sections dedicated to different topics, in no particular order, but I’ll try to keep the most controversial opinions for the end.
I hope that this article will be interesting and useful to you, but keep in mind that I surely missed many important points and all my personal biases went into it.
It’s kind of crazy to think about it, but AndroidX preview was announced just one and a half years ago. It became stable about a year ago, and at that point Google also stopped further development of the legacy support libraries. [the moment I wrote this sentence I recalled that I asked this question about the motivation behind support libraries on StackOverflow back when I was totally “green” Android developer]
The usage of the term “stable” to describe AndroidX is a bit ironic, though, because nothing about this set of artifacts is stable. Google constantly adds new libraries and frameworks under
androidx. namespace, and many “old” APIs (which are barely one year old at this point) evolve at a very fast pace.
To this day I migrated two applications to AndroidX. It went alright and I don’t remember many surprises. Jetifier, the tool that redirects transitive dependencies on support libraries to their AndroidX counterparts, also worked surprisingly well. However, even though the applications weren’t big, it wasn’t a “one-click migration” either.
I’m also involved in one project which hasn’t migrated to AndroidX yet (and it’s not even on the roadmap). No problems there. Looks like this is also a viable course of actions in some cases.
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. You’ll most probably need to migrate at some point anyway, so it’s better to do it on your own terms, instead of migrating in a rush when you’ll need some new AndroidX library in six months.
After discussing AndroidX I must mention Jetpack, of course. As far as I remember, Jetpack started as an umbrella for “architecture components”, but expanded to incorporate most (or even all) APIs from AndroidX. Therefore, as of today, I don’t see any meaningful distinction between AndroidX and Jetpack. Except for, surprisingly, marketing and PR.
When you look at Jetpack’s website, it does’t look like a resource for technical documentation. It looks like a landing page of an early-stage SaaS startup.
Take for example these “testimonials”:
Or this “trusted by” section:
Given such a focus on marketing and PR, I won’t be surprised if Jetpack files for a standalone IPO in 2020.
Seriously, though, there is something deeply concerning about this attempt to “sell” APIs to developers in your own ecosystem. Like, why the hell would anyone want to actually advertise ViewModel in search?!
All in all, since Jetpack just aggregates stuff from AndroidX, what I wrote earlier about AndroidX is applicable to Jetpack in large part as well. Below I’ll also discuss some of these APIs individually.
Perfoming work when the application is not in the foreground has been one of the most dynamic use cases in Android. You could leverage regular “started” Services (as opposed to “bound” Services) for that before the introduction of doze, SyncAdapter, GCMNetworkManager, FirebaseJobDispatcher, JobScheduler and, lately, WorkManager. These are just Google’s own APIs that I can recall from the top of my head. There were also a bunch of third-party solutions like Android-Job.
However, Google announced recently that they are going to “unify background task scheduling” around WorkManager API. This sounds great, but, for some reason, I can’t get rid of deja vu feeling when I hear that…
Anyways, whether unified or not, WorkManager doesn’t solve the most serious issue with background work: reliability. I won’t go into explanations here, but remember that if you ever need to implement background work in your app, start by reading all the information on dontkillmyapp.com. In addition, read and star this issue in Google’s issue tracker.
TL; DR; background work story in Android is a mess and the fragmentation makes it very nuanced and unreliable.
In the past, I’ve been advocating for background syncs of data and other types of background work whenever possible. I probably was one of the last fans of SyncAdapter. However, today, given the reliability issues, I advocate for the opposite: avoid background work whenever possible. If your PM insists on this feature, show them the above links. Explain them that background work can take hundreds of hours of effort to implement, and still bring more troubles than benefits.
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.
There are no surprises in the world of SQLite ORMs – Room dominates the landscape. Starting with version 2.2.0, Room finally supports incremental annotation processing. Keep in mind, though, that your architecture shouldn’t care which kind of ORM you use. Therefore, when it comes to Room, “architecture component” is just a marketing term, not a technical role.
The main contender for the crown of ORMs in Android is SQLDelight. This library is much older than Room, but, as far as I understand, it had been pretty much rewritten during the past year or so. Unfortunately, it’s only targeting Kotlin now. On the other hand, SQLDelight supports Kotlin multiplatform. Therefore, as Kotlin adoption rates increase, I expect the adoption of SQLDelight to increase as well.
By the way, there are mirrors of bare SQLite consturcts in AndroidX namespace. I’m not sure what to make of it, but if you use bare SQLite in your apps, then maybe it’s worth exploring this topic.
In addition, let’s not forget non-SQL databases for Android like Realm, Parse, Firebase, ObjectBox and others (some of them still use SQLite under the hood). If I’m not mistaken, most of them (or even all of them) come with automatic data synchronization capabilities. There was a period of time when these solutions were relatively popular, but, as far as I can tell, they aren’t anymore. That said, I wouldn’t discount non-SQL databases with auto-syncs right away.
Last year I wrote very complex Android app that integrated with Parse Server. The app had full offline support, server-side localization, user-specified system and content languages, very complex multimedia and more. I used Parse SDK for Android and, Except for minor WTFs, the experience was surprisingly good. Maybe that’s not the best solution if your company already employs a bunch of backend folks, or you need to implement lots of server-side logic, but it might be a game changer for startups and individuals who perform just CRUD operations on backend.
Just one warning: if you’re going to take Database-as-a-Service solution (e.g. Firebase), make sure that you understand its long-term costs and implications.
Much more “interesting” development happened in the context of external storage.
If your app targets API 29 or above, the standard access to files on phone’s external storage won’t work anymore, with few notable exceptions. Instead, you’ll need to use SAF framework which (supposedly) allows users a more granular access management. Unfortunately, SAF works in completely different manner, so a major refactoring might be required in some apps.
Google wanted to roll this requirement out for all apps starting with Android 10, but it generated such an outcry from the community that they decided to postpone this feature. Therefore, you can still work in “legacy” mode even if your app targets API 29 by setting a special flag in your build files. However, it looks like scoped storage access will be enforced in the next version of Android for all apps, regardless of their target API level.
I haven’t worked with scoped storage until now, but from the many discussions I read on the internet, it looks like implementing it might be a challenging task. Therefore, if your app uses external storage in “legacy” mode and none of the exceptions apply to it, you better start refactoring and testing it right now.
Couple of weeks ago a new framework was added to AndroidX family. Its commit message says:
New library meant to replace SharedPreferences. The name is not final, this is just for implementation review and to support the design doc (feel free to request the design doc privately)[…]
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.
The main difference between SharedPreferences and this new framework is that the latter is asynchronous by default. In other words, instead of just getting the value of a specific key, you’ll need to implement a callback that will be notified with the value at some later time.
If you’re curious about the motivation behind this move to async notifications, you can read this StackOverflow answer. Reddit user Tolriq shared their numbers concerning the probability of hitting this bug here. In their specific app it affects
1 / 10,000 / SESSIONS_PER_USER_PER_MONTH fraction of user sessions. That’s maybe not that bad in general purpose applications, but might be a deal breaker when high reliability is required. For example, in cars with Android Auto, application hang and subsequent crash can distract the driver, which can lead to very unfortunate consequences.
In the land of dependency injection, the biggest news is the effective deprecation of Dagger-Android. This statement immediately requires two clarifications. First of all, I say “effective” deprecation as opposed to “formal” deprecation because it hasn’t been officially deprecated yet. Second, Dagger-Android is not the entire Dagger 2 framework, but just relatively recent addition to it. I wrote a very detailed artilce on this subject, so I won’t repeat myself here.
As for other dependency injection frameworks, I don’t see them as real contenders to Dagger. Koin, for example, might be nice, but I don’t believe that it’ll get much traction. In fact, I believe that it got a bit of initial adoption due to just two main reasons. The first one is Dagger’s awful documentation which makes it very difficult to approach. Koin is light years ahead of Dagger in this context. The second reason is the fact that 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.
What I do think might happen, is a very slow appearance of Pure Dependency Injection (aka. manual dependnecy injection).
Now, Google claims that “manual dependency injection cost grows exponentially as your app gets bigger”. In my opinion, it only shows that they neither understand what “exponential” means, nor did they actually “measure” anything. This statement is plain wrong and I’d expect Google to not mislead the community in such a manner.
The truth is that Pure Dependnecy Injection is actually relatively common in backends (especially with microservices, where you don’t want to add dependency on the framework in each service) and it works alright. However, reflection is also a valid option in backends. Therefore, they don’t usually need to resolve to compile-time code generation if they want to use dependnecy injection frameworks.
The situation is different in Android, though. We can’t use reflective DI frameworks, so we use Dagger. Well, in fact we can use reflective frameworks and for most projects it’s alright, but “OMG performance”. Now, I’m not saying that using reflective frameworks is safe, but it’s definitely not black and white decision. In any case, Dagger is de-facto standard in Android and we all use it. However, despite the nice green graph for Dagger’s cost in the aforementioned Google’s presentation, its cost actually grows the fastest with time. There are three factors here: 1) the more code you have, the more time it takes for annotation processing to run during build 2) the more developers you have, the more builds they’ll execute and 3) all developers need to learn Dagger, which takes a lot of time.
In other words, while Dagger indeed allows you to write less code, it consumes much more effort on bigger projects due to its effect on build times and required education.
On bigger projects build times become real issue and constitute major productivity bottleneck. 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.
One of the main reasons developers adopt DataBidning is to eliminate
findViewById() calls. To be honest, I never had problems with these Views lookups, but they’re indeed just boilerplate and I wouldn’t mind to get rid of them. However, slight annoyances with
findViewById() calls did not justify DataBinding usage, in my opinion. The good news are that very soon we will be able to remove these calls without DataBinding using another new feature: ViewBinding.
In fact, I never believed in DataBinding. It felt as too complex solution for the problems it (supposedly) addressed. In addition, DataBinding allowed developers to put logic inside XML layouts. Experienced developers don’t use this approach because it sounds like a sure recipe for maintainability hell, but the sole fact that DataBinding opened this door is yet another drawback of this framework.
Back in November 2016, when DataBinding was at the top of its hype-waive, I made the following prediction in this StackOverflow answer:
However, there is one prediction I can make with a high degree of confidence: Usage of the Data Binding library will not become an industry standard. I’m confident to say that because the Data Binding library (in its current implementation) provides short-term productivity gains and some kind of architectural guideline, but it will make the code non-maintainable in the long run. Once long-term effects of this library will surface – it will be abandoned.
Now, I don’t have any numbers concerning DataBinding’s adoption, but it’s quite evident that it didn’t become industry standard. I’ve never seen a professional project that used it myself, and I rarely meet developers who use it in their applications. In my estimation, once ViewBinding will mature and become widely adopted, DataBinding will fall in popularity even more and become “legacy” framework.
Preserving State on Configuration Changes
Since the introduction of ViewModel “architecture component”, the story of configuration changes in Android apps became a shitshow. I know that it’s a harsh statement, but, in fact, it’s the most moderate expression I can think of to describe the situation.
Fortunately for me, Gabor Varadi (aka. Zhuinden) already summarized the first act of this shitshow in this post on Reddit, so I don’t need to do it myself. TL; DR;
onRetainCustomNonConfigurationInstance() was deprecated in favor of ViewModel. Twice.
Interestingly, at the end of that post, Gabor made some tongue-in-the-cheek predictions:
And you know what? Retained Fragments are getting deprecated now! Gabor, wellcome to “Cassandra club”.
In my opinion, deprecation of retained Fragments is actually a good idea. See, the only reason Fragments have
onDetach callbacks is to support this use case. With deprecation of retained Fragments, these methods can be deprecated too and Fragment’s lifecycle will be simplified. If you used my approach to Fragment’s lifecycle, this deprecation shouldn’t bother you at all because I long recommended to avoid retained Fragments and forget about
However, while there are some good reasons to deprecate retained Fragments, deprecation of
onRetainCustomNonConfigurationInstance() is bullshit. And this time it’s not my words, but Jake Wharton’s (you can read his opinions as the top comment under the aforementioned Gabor’s post on Reddit). I sometimes disagree with Jake, but this time I couldn’t say it any better myself. There is simply not a single reason to deprecate this method. Especially given the fact that ViewModel by itself uses the same mechanism under the hood.
What should we make of these deprecations? I can see only one explanation: Google is determined to force all Android projects to migrate to ViewModel, regardless of its technical merits. They are willing to deprecate all existing alternatives to achieve their goal, even if these alternatives are actually superior to ViewModel itself.
Sounds a bit conspiratory, right? I agree. But, fortunately, there is a simple test for this theory.
See, while I don’t like the deprecation of retain-non-config-state mechanism, it doesn’t affect me in any way because I don’t use it. In fact, absolute majority of applications don’t need it. And they don’t need ViewModel either. All you need to properly handle config changes is
onSaveInstanceState(Bundle) callback. It’s much simpler and better approach because it also handles save & restore flow (aka. process death). So, as long as I can save the state in this manner, I’m alright. And I’m not the only one in this boat. Despite Google’s heavy marketing and PR, many experienced developers realize that ViewModel is unneeded complication and there are better ways to both architect your app and preserve state on config changes.
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.
However, given Android’s memory management mechanism, Google can’t just deprecate
onSaveInstanceState(Bundle) without providing a reliable alternative. “Luckily”, they already work on saved state module for ViewModel.
I guess that in one-two years we’ll know whether this theory has any merit.
All in all, as I said in the beginning of this section, since the release of ViewModel, configuration changes story in Android became a shitshow. More than two years ago, when I wrote the post titled Android ViewModel Architecture Component Considered Harmful, I predicted that ViewModels will be a waste and will further require save & restore hacks at some point. All my predictions came true, but, unfortunately, the reality turned out to be even worse than that.
The most important development in the domain of concurrency APIs in Android is, of course, deprecation of AsyncTask. I already wrote a very detailed article on this subject with specific recommendations, so I won’t discuss this matter again here.
Now I’m going to say something that will alienate many readers. Please, try to not take it personally.
Another popular framework for multithreading in Android, RxJava, quickly becomes “legacy”. It’s quite evident from this StackOverflow Trends graph:
Now, many developers challenge this statement, saying that this data is not representative and that there are other ways to interpret this graph. That’s probably correct, and I’m not data scientist myself. However, I don’t see any other explanation for the very distinct maximum in this graph, and the fact that RxJava’s curve has the same slope as AsyncTask’s one.
Therefore, if you haven’t invested time into RxJava yet and your project doesn’t use it, then I recommend avoiding it. In fact, this was my recommendation all along, but today it’s also supported by data.
If your project already uses Rx, don’t panic. There is no need to refactor anything immediately. Especially if you’re a single developer, or the turnover of staff is slow. However, keep in mind that, going forward, it’ll be more and more difficult to find developers experienced in Rx. Therefore, extensive usage of Rx in projects will probably require more time for new developers to ramp up on it. Eventually, projects that use Rx extensively will be considered “not cool” (like projects with AsyncTask and Loaders today).
I understand that this discussion of RxJava cuts close to the bone for many developers. They invested weeks into learning RxJava, maybe even convinced their teammates to use it in projects, and now I’m saying that it’s “legacy”. How dare I? Once again, all I can say is that it’s not personal. I simply analyze the situation and make predictions based on what I see. I might be wrong too. But if I’m right, I’m just the messenger, so don’t shoot me.
In Kotlin world we have Coroutines. I implemented some non-trivial use cases using Coroutines recently and found this framework to be quite nuanced, complex and relatively immature. Even found a bug.
There is a widespread claim that Coroutines make concurrency simpler. I never bought it because I know that concurrency is fundamentally complex, but now, after I got some hands-on experience, I can say with confidence that Coroutines aren’t all rainbows and unicorns. In my opinion, coroutines actually add complexity, so I recommend to approach them carefully.
On the other hand, looks like Coroutines are going to be Kotlin’s default concurrency primitive. Therefore, I do think that you need to invest time and learn to use them if you write Kotlin code.
There is also Flow framework which, as far as I understand, adds stream processing operators on top of Coroutines. It became stable just couple of months ago, so I can’t say anything about it right now.
Now let’s discuss the state of Kotlin in Android. From the past experience I know that this is very sensitive topic and, regardless of my efforts to be objective, shit hits the fan very quickly. However, I think it would be professionally dishonest on my side to summarize the state of native Android development and skip Kotlin. Therefore, I’ll just ask you once again to not take anything I say personally.
The most important fact you need to know about Kotlin in Android is that it can severely increase your build times.
In this post you can read about my own informal benchmarking of build times with Kotlin. The results were +18% for clean builds and +8% for incremental builds.
Then Uber published their own research in collaboration with JetBrains. Their results draw much more negative picture. Based on these results, it looks like if you don’t use annotation processors in your application, then introduction of Kotlin can potentially multiply your build times by a factor of four! If you do use annotation processors, then Kotlin will add 50%-100% to your build times.
Uber’s results are consistent with the metrics obtained after migration of OkHttp to Kotlin: x4 increase in compilation time.
If you’re absolutely astonished by these numbers, then don’t worry – it’s not your fault and you’re not alone. This subject, although of utmost importance, isn’t being discussed widely and I get an impression that Google tries to sweep it under the rug. When I asked one developer, who is closely familiar with the matter, after a very interesting discussion, whether I can quote them on this topic, they said “I prefer not; it’s a delicate matter”.
In addition to slow build times in general, support for incremental annotation processing in Kotlin was non-existent until this week. For comparison, it has been available for Java since about 10 months ago.
Two years ago I wrote this post to warn the community about potential dangers of early Kotlin adoption. I got a lot of heat for this article (as you can see from the comments) and became “Kotlin hater in chief” for a long time.
However, if you read that article today and keep the aforementioned metrics in mind, you’ll realize that I actually underestimated the problems. Build times are one of the worst productivity killers on bigger Android projects and the fact that even today, more than two years after “official adoption”, Kotlin is still so much inferior to Java, speaks for itself. Whatever other benefits Kotlin brought, all of them have probably been negated manifold by longer build times.
That said, we should not ignore the fact that Google pushes the ecosystem to Kotlin and its adoption steadily increases.
I, personally, didn’t choose Kotlin for new projects that I started so far. It was too immature and I don’t believe that my clients should pay for my education, or, alternatively, that I should waste my own time on Kotlin. However, starting now, I’ll give Kotlin a serious consideration for new projects. I already tried it on several pet projects and it looks like its evolution finally slows down. Again, I don’t agree with developers who say that you must use Kotlin on new projects. It’s still a trade-off. However, Kotlin became a real contender in my opinion.
As for whether you should migrate existing projects to Kotlin or not, I can’t give any general recommendations. It’s a multi-variable problem that needs to be discussed on case-by-case basis. However, if you do decide to start a migration (or already started), this post that contains some warnings might be useful to you.
Allow me to describe my activities in context of Android development:
I started three new applications in the past two years. I always strive to have at least one client where I do hands-on development. I jump into existing projects and analyze the long-term effects of earlier technical decisions. I write this blog. I produce advanced courses on Android development. I spend too much time arguing about Android related topics on the internet.
However, despite all the aforementioned activities, today I feel like I can’t keep up with changes in Android ecosystem.
If that’s what I feel, I’m really sorry for less experienced Android developers who need to navigate their way. And I don’t even want to imagine how it feels to learn Android development from scratch today. By the time you get comfortable with the framework and the tools, many of them will be outdated or deprecated. It’s probably the worst time to join this, otherwise amazing, community. Google is very proud about their “inclusivity”, but looks like it doesn’t apply to less experienced developers.
I, personally, think that Google’s actions in context of Android framework lead to enormous waste of human potential. It takes hours just to read about all these changes, let alone actually implement them. I’d prefer to spend this time more productively, creating value, instead of chasing my own tail.
In this post I tried to summarize the important info about the current state of native Android development. I also made some predictions about the future. Now, I’m sure that this post isn’t perfect: it probably contains some inacurracies and I surely missed additional important points. Feel free to correct me in the comments below. But please keep in mind that nothing in this article is personal. I know that I brought up some very controversial points, but that’s what I believe to be true.
I also referenced some of my older posts in several places. I did it not to show off and say “look, I was correct!”, but for you to be able to read my predictions from the past and compare them with what actually happened. When I wrote these articles, they read just as crazy as this one reads today. But the predictions I made turned out to be quite accurate.
Well, whom do I kid? Sure thing I also want to say “look, I was correct!”. Given the huge professional risk I take by publishing these controversial predictions, it’s a huge relief to know that I didn’t mislead my readers. Even though sometimes I’d prefer to be absolutely wrong and Google to turn out to be a real partner. As of today, that’s not the case.
As usual, thanks for reading. You can leave your comments and questions below.
24 comments on "The State of Native Android Development, November 2019"
Hello, thanks for your overview.
I’m glad I mostly don’t do Android programming anymore.
I have two additional comments
The first is, as I shared on Twitter, that migrating from the Android Support Libraries to AndroidX SHOULD BE a one click migration.
There is no point in migrating one project, it’s the entire ecosystem that needs to be migrated.
I am working on this, can’t promise when it will be done, but here is a teaser
The second thing:
As a mostly not Android Kotlin developer, I am getting really annoyed that the two terms are getting synonyms.
This is a necessary context to some of the things that you say that are not wrong but incomplete.
For DI on Android, please use Dagger or Manual DI or whatever suits your needs.
But it doesn’t follow that Koin is useless. I am using it to build microservices on the backend side.
Same for coroutines. I have no insight whatsoever of what problems you have with them on Android.
But don’t forget that Kotlin is not Android. Coroutines are an absolute joy to work with in Spring Boot for example.
SQLDelight is targetting Kotlin only?
That’s probably because they made they realized that competing purely on Android against a library made by the Android team is too hard.
No matter how bad the “official” library is (even if in this case Room is Good), people prefer to use it over a better alternative by a “third party”.
So it makes sense that there are targeting a different set of users.
Hey, thanks for your comment.
Everything in this post is just about Android development, as stated in the intro section. In addition, I didn’t say that Koin is useless. I said that in my estimation it won’t get much traction in the ecosystem.
I just started learning Android about half a year ago and you addressed most of challenges I face as a new comer. Like you rightly said, I started learning AsyncTasks and boom!!! it got deprecated some weeks ago. It’s really a rough time to join Android development and your post have greatly help me get some perspective. I hope I become a good Android developer some day. Thanks
I’ve been thinking about your point on how ridicoulous it is to buy ads, add “user testimonials”, … to push “Jetpack” to whoever don’t need it.
The Android Framework team is kind of the South of my design compass.
Whenever they do something that doesn’t feel right,
I ask myself whether doing the exact contrary would not make sense.
And yes, that worked again in this case.
All library authors produce tools that they are proud of and tell people who might need it about it.
Good library authors go one step further.
They take care of explaining in which context the tools they produce originated, and warn that it is not for everone.
Dan Abramov : You Might Not Need Redux
Hi. Thank you for your articles, it’s always interesting to read.
I’m curious if you thought about cross-platform app development. There are some solutions like C++, React Native or Flutter, but all of them are quite radical. Entirely new ecosystems.
In the meantime JetBrains came to a solution when they can offer something that will handle all the business logic (up to storage and network communication) in a Kotlin/Multiplatform module. Bet you heard about it but in short it’s a Kotlin code compilation to native code with LLVM in iOS, in JVM bytecode in Android and to js in web.
This approach may have its advantages like native components (activity, fragment, recycler) at the highest level and common logic at lower levels. There are some real life projects migrated to this approach and they are quite satisfied, despite some current tech limitations.
Soon JetBrains will update state of the Kotlin/Multiplatform at the annual Kotlin conf. And they announced a new product launch at the conf. There are some rumors that it’ll be Kotlin IDE for a cross-platform dev (backend, web, mobile). Will see if I’m right or not. https://www.youtube.com/watch?v=w6AxZ_Xraf0
Thinking in this way overwhelms all the negative and controversial points of Kotlin/Coroutines/etc. Only imagine that all your app’s runtime is working in common module in Kotlin instead of triple bugs and coding several platforms in the old-fashioned manner.
I realize that it’s like a holy grail to do cross-platform development, but in my opinion this approach could be successful. What are your thoughts on this?
I should probably put my thoughts about cross-platform in a post sometime because I get asked about it quite a bit. I’ll try to describe my general opinion, but I don’t want to host further discussion of cross-platform here.
If cross-platform will ever work, it will be amazing. However, the experience of the past ~10 years shows that there are some fundamental obstacles to overcome, not necessarily related to technology. Therefore, even though Flutter had an amazing start, I still prefer to remain sceptical about it. Kotlin Multiplatform is not even there yet.
I thought about it a lot and came to this idea: cross-platform solution will work only if it’ll be the main native solution for at least one platform.
An interesting point that might be worth added to this list is Bazel + Android as an alternative to Gradle. Large mobile shops such as Lyft and Uber are actively adopting it for building their apps. Google’s development work on Bazel Android ruiles has been fairly opaque but is certainly happening. It’ll be interesting to see how the Bazel VS Gradle story plays out long term.
In the Concurrency section you didn’t propose any solid alternative to rx. What concurrency tool do you think one should use? Is it coroutines?
I discussed the concurrency landscape in my previous post about AsyncTask.
I, personally, use my own ThreadPoster library in Java, but will probably switch to Coroutines in Kotlin-only projects.
Part of the problem is so many vocal developers have a “wanna be jake wharton” syndrome and they keep pushing their agenda in the name of conference driven development. I’m sure it helps them with reach, job offers, fame etc but it added so much of confusion in the last 4 years for new developers.
This is the only reason Android team’s initiative like Jetpack are gaining traction. It doesn’t matter what is right, they just want something pragmatic and official recommendation is one way to go about it. Not to mention the Square fan boys agenda adding more noise.
I think you’re very wrong.
First of all, you greatly overestimate the influence of conference talks on new Android developers. Most developers (not just new developers) whom I spoke to don’t watch conf talks on YouTube and don’t go to conferences.
Second, Jetpack initiative is “gaining traction” because it’s Google’s creation, so it’s automatically seen as the best option by many devs, and it gets very fat marketing and PR budget. There is no community-generated solution or library that would have an army of professional developer advocates.
Third, your “wanna be jake wharton” definition sounds very personal. I’d look into that if I’d be you.
Nonetheless, thanks for your comment.
I didn’t say which approach or group or company is right or wrong. I’m just saying that there is a fatigue in the developer community for new developers given all this noise (something that you ack in your article).
Given that and the fact things like RxJava was hyped and now slowing down, teams tend to go with pragmatic solution and that happens to be JetPack and what ever Google recommends. For these teams, technology is just a means to an end for their business use case. They don’t care too much about right or best or whatever, they need to think of other things like employee turnover etc.
And didn’t mean anything personal, just saying few folks in the community have their own agenda, which is totally fine except that new developers might not always get the right input.
And you didn’t even talk about Jetpack Compose…
Exactly, that’s going to be a hell of a change.
I considered adding it, but there is not enough info about Compose at this point and, hopefully, no one will try to use it in production in the coming year. I’ll definitely write about it once it matures a bit more and they consolidate its core architecture.
Hi, thank you for such article, it’s really pithily. And I have question about this sentence “We can’t use reflective DI frameworks, so we use Dagger. Well, in fact we can use reflective frameworks and for most projects it’s alright, but “OMG performance”.”.
Why the question has arose:
1. At the beginning before dagger we used Guice, and it was not good but more less acceptable by performance;
2. Then Dagger 1 and it was better and it was usable;
3. And nowadays we have 8 cores cpu, 6 gb RAM etc.
4. Is this a real problem when it takes (off the top of my head) 200ms to scan and inject instead of 10ms when we have api calls for 1-2 seconds?
5. Dagger 2 compile time despite improvements still kills a lot of time;
6. Reflection despite cons can bring some benefits also.
I wonder is it still a real problem in your opinion?
Thanks for you comment.
Reflection in Android is still a problem, but it’s not as bad as you could think based on what you read on the internet.
These 200ms that you mentioned are not exactly equivalent to API calls because the later usually take place on background threads, while injection delay can make your app start slower or introduce delay in transitions between screens. So, it’s still a potential issue that you need to keep in mind. In this context, you might find this thread that contain some numbers for Koin interesting.
However, since Dagger is so complex and adds a significant overhead to build times, I believe that reflective DI frameworks and Pure DI are being under-employed in Android world and there is a potential for improvement.
But all of that is just theoretical discusssion. As of today, if you’re going to use DI framework in Android apps, I surely recommend Dagger.
It’s like living in hell with creative devils that invent new tortures each day!
In august 2017 I’ve started my first ever android project, at that time ReciclerView was the minimal “cool piece” you have to master to be considered human.
I’ve chose Kotlin, and anko(now deprecated), as main tools It was very hard time but in two months I did the job (including sqlite)
Then I have to move the app for using remote database, so I selected grpc and the google cloud , on the mean time android architecture appeared, I’ve learned the basics of livedata, koin . That toke a lot more effort and time, I can’t list all the oddities I have to deal with, from constraint layouts to the Themes dark or hollow …..I’ve stopped the version on may 2018
In august 2019 I did have to remake the app.
First anko looked as dying but compose was not easily available , then I have to migrate to androidx, on server side I switched to exposed…
And right now I’ve revamped the first activity in my old app (Login with a splash window) with jetpack compose, and I ask myself SQLdelight Room or does Expose work in android? (anko is death), one single activity or many, koin or not to koin …. , navigate or not navigate …..ViewModel…..coroutines….
The only thing I’m sure about is that no matter witch package, library or framework, I will, no doubt about it, find a very smart writing proving with no doubt that I’m about to been cheated and send to hell If I ever dare to use it.!
I started learning android dev about a year ago , i am probably a slow learner. I just learned about AsynTask and wow , now it is deprecated.
What do you use for background tasks?
In Java I use my own library called ThreadPoster. In Kotlin, I’d use either ThreadPoster or coroutines.
what do you think about the Jetpack Compose.
Too early to say anything specific, but it’ll surely be a major change in Android landscape. We’re probably more than a year or even two away from the moment when Compose will implement all the features of the existing Android UI framework, so I don’t see any pressure to explore it.
I started software development in 1978 and I have never seen an architecture so poorly designed as Android. Sadly, a lot of software development has been like this for the past 20 years. It doesn’t seem like it was even architected – just stuff thrown together – and then parts deprecated or fallen by the wayside when something else becomes the current fad, only to be replaced next year.
That something is deprecated or fails to work in the next version indicates that it wasn’t sufficiently planned to withstand the test of time. It would be as if the construction industry suddenly decided to deprecate two-by-fours (2×4), or mathematics decided to deprecate algebra or geometry!
The amount of needless churn is truly amazing and wasteful. I started to learn Android development a few years ago as a hobby and gave up. Thanks for the article; it confirms why I moved on to other interests.
“And I don’t even want to imagine how it feels to learn Android development from scratch today.”
I’m a beginner developer with 6 months of core java and 3 months Android under my belt. Although I like diving deep into solving problems and figuring out how things work, I can confirm that I have greatly underestimated the steep learning path of Android. Google is also making it very hard to learn everything from scratch, especially for beginners. Stackoverflow solutions from 1 year ago can easily be outdated and even their own Google course is using a lot of deprecated stuff. Makes me wonder, what the real reason behind everything is.. They are promoting Kotlin so hard, it’s crazy.. Probably their war with Oracle? Who knows..
Anyhow, Java knowledge from 10 years ago is still relevant today, but can’t say that for Android honestly.
I am a novice Android Developer. After reading your analysis, I was daunted. It was then when I realized that some of my difficulties in learning developing android apps were due to the platform itself. Fortunately, it does get better. Kotlin is even more mature. I still have some doubts about choosing lifecycles components over Rxjava.