The annual Android Dev Summit conference, which took place last week, brought lots of interesting news and announcements. One major announcement, which went by largely unnoticed, concerned Dagger-Android: Google stops its development. In my opinion, this is huge.
However, this announcement confuses many Android developers and gives rise to much uncertainty and doubt. “What do you recommend instead of Dagger” – I got this question way too often in the past couple of days. And, to be honest, maybe I even unintentionally contributed a bit to the overall confusion. Therefore, I decided that this subject requires a more thorough review. In this post I’ll explain the current situation around Dagger and share my opinion about the future of dependency injection in Android applications.
History of Dependency Injection in Android
There is Dagger and there is Dagger. They look similar (identical, in fact), but they mean different things.
Confused? That’s the standard reaction of new Android developers who start learning Dagger. To make the terminology clear, allow me to take you on a short trip into the history of dependency injection in Android ecosystem. In my opinion, this info will be useful to you even on its own, because it’s important to have a perspective on these things.
A long time ago in a galaxy far, far away… Android was born.
The ecosystem was young and there were practically no design or architecture guidelines. Developers back then used “god Activities” (Activities having thousands lines of code) left and right. These were dark, but interesting times. Well, at least in my imagination. I myself became Android developer at a much later stage. Therefore, my own historical perspective is probably incomplete, so take it with a grain of salt.
Anyway, even back then, there were prophets of clean and maintainable code walking among mere mortals. They wanted to bring into Android ecosystem the practices that had already proven themselves in other stacks. One of these practices was “dependency injection” (or, in short, DI).
Now, I won’t go into explanation of what dependency injection is in this article. I already wrote a lot about it in this blog and you can easily find this material. The only two things that you need to keep in mind while you’re reading this post is that (1) dependency injection is a fundamental architectural pattern and (2) it’s a very complex concept. I know that there are many people out there saying that DI is actuall a simple concept. Don’t buy it. Simple concepts don’t generate continuous stream of tutorials, posts and frameworks. More importantly, simple concepts don’t frustrate new developers the way DI does.
So, “clean code prophets” wanted to introduce DI into Android ecosystem. However, implementing DI manually is tricky and erro-prone. It’s not bad, it scales alright and it doesn’t take too much effort. It’s just not what most projects need. Luckily, other ecosystems had already figured out the solution to this problem: dependency injection frameworks.
Dependency Injection Frameworks in Android
Dependency injection frameworks are tools that assist in implementation of dependency injection architectural pattern. They provide a “template” that even inexperienced developers can follow to achieve good results. In addition, DI frameworks embrace “convention over configuration” paradigm, thus allowing developers to use pre-defined conventions to replace explicit configuration. For example, by convention, many DI frameworks can initialize fields annotated with @Inject annotation, instead of you doing it manually in code.
The first DI framework that became popular in Android was RoboGuice. It was ported from Guice, Google’s DI framework for Java, so it made sense. Then, developers from Square rolled out their own framework called Dagger. Then Google took over Dagger and introduced yet another framework called Dagger 2. You’d think that three frameworks to address the same concern would be enough, but no. Today we also have Toothpick, Kodein, Koin and, probably, few others that I forgot.
So, we’ve got a lot of DI frameworks in Android world. However, most of them are largely irrelevant. For the past years we’ve had just one single dominant framework in Android ecosystem: Dagger! But… There were at least two different Daggers. So, which one is the dominant? Well, it’s complicated.
Dagger, Dagger 1, Dagger 2, dagger.android, Dagger in Android! WTF?!
Now let’s clarify the “Dagger’nology”.
The original framework by Square was called just Dagger. However, today, you’d say Dagger 1 explicitly if you’d refer to it. It’s officially deprecated and you can pretty much ignore it.
Google’s framework, which became dominant in Android ecosystem, was originally called Dagger 2. Sometimes we still refer to it as such, but, in most cases, we simply call it Dagger today.
Then, in March 2017, version 2.10 of Dagger was released. This version introduced a new way to integrate Dagger into Android apps. Since this “new way” was packaged inside
dagger.android package, it quickly became known as Dagger-Android.
Dagger-Android is Dead
Now, after you understand the terminology, I can go back to the announcement from Android Dev Summit.
You can watch it here. I’ll quote the main parts:
Dagger-Android […] was an attempt on our part to make Dagger simpler in Android, but it didn’t work. We heard from you that it doesn’t solve the problems that you really have in your daily jobs. […] We are stopping it’s development […] because we think we can do better and we can have other ways to simplify Dagger.
What it basically means, is that after about two and a half years since its introduction, Dagger-Android is dead.
It’s important to understand that it’s just about Dagger-Android. “Standard” Dagger remains the dominant dependency injection framework in Android world and doesn’t go anyway in the observable future. In addition, interestingly, they’re already working on some other “ways to simplify Dagger”. I’ll address this part later in the article.
What Was the Problem with Dagger-Android
At this point, it’s worth taking time to understand why Dagger-Android “didn’t solve the problem developers have in their daily jobs”. However, keep in mind that what you’re about to read is just my personal opinion. Many developers, whom I hold in high respect, disagree with it.
Setting up “standard” Dagger in your Android applications is not that difficult once you understand the principles. But that last part, understanding principles, is crucially important and actually difficult. And it’s not just about knowing Dagger’s APIs. You also need at least some intuition about dependency injection architectural pattern in general.
To make developers undersand DI and Dagger you need good documentation, but Dagger’s official documentation was terrible. It was so bad, that it’s sample, the notorious Thermosiphon, became a meme among developers. Since the official documentation was bad, developers always had to learn Dagger from community generated content. Blogs, basically. And as much as I like community generated content, much of it is as confusing as the official Dagger docs and teaches really bad practices.
So, the docs were bad, thus developers were frustrated and complained. At this point, it would be reasonable to expect Google to invest some major effort into writing good documenation, or adopting some community generated content as the official documentation. Instead, they decided to introduce Dagger-Android. The idea was to “simplify” Dagger with another layer of abstraction over “standard” Dagger. It didn’t eliminate the need to learn the old approach and, in addition, introduced a bunch of new constructs and nuances. All the while, the docs still sucked.
This attempt failed miserably. The complexity sky-rocketed. The frustration evolved into real pain. Heated arguments around Dagger-Android’s utility became routine in the community. In short: Dagger-Android created a real mess.
Since the problem had always been lack of good official documenation and tutorials, it couldn’t be solved with additional complexity. Therefore, Dagger-Android had been destined to fail even before its first line of code was written.
Dagger-Android is Effectively Deprecated
Couple of days ago I wrote on Twitter that Dagger-Android is “officially deprecated”. Several developers called me out on this and said that it’s not what they said. And then Google’s representative, who announced the “death” of Dagger-Android, wrote that it’s not deprecated.
I felt that I might’ve overreacted and, maybe, even misled others. But then I listed the facts that we know:
- Google admitted that Dagger-Android “experiment” didn’t work because it didn’t solve real problems
- further development of Dagger-Android is stopped
- some new solution is already in the works
Recall that deprecation doesn’t mean that something doesn’t work anymore or removed. Camera API has been deprecaed since API 21, but is still actively used by many applications. It just means that some approach shouldn’t be used going forward, and it might be removed at some point in the future. Taking that into account, the current state of Dagger-Android sounds very much like deprecation to me.
And then, it’s important to note how exactly Google formulates the fact that Dagger-Android is “NOT deprecated”:
So, they’re “committed to maintain it until stable suitable replacement is available”. First of all, that’s exactly what deprecation means. Second, stable suitable replacement is already available. In fact, it has been availale for the past five years: “standard” Dagger, without additional complexity on top.
Therefore, allow me to correct myself: Dagger-Android isn’t officially deprecated. It’s effectively deprecated and we’re waiting for official deprecation.
Which Dependency Injection Framework Should I Use?
Many Android developers probably ask now: so, given the deprecation of Dagger-Android, how do I do DI in my application? Moreover, there are developers who learn Dagger just to increase their chances of landing a job. Should they switch to another framework, or, maybe, just stop wasting time on dependency injection at all?
Before I share my opinion, let me show you Google’s answer:
So much for “Opinionated Guide to Dependency Injection on Android” (that was the title of the talk at Android Dev Summit).
I, personally, never believed in Dagger-Android. I think it’s good that it’s deprecated now. In fact, I think that Google needs to officially deprecate it right now.
If they already know that it “didn’t work”, and they are working on a different solution, then why let developers deal with it at all? Wouldn’t it be reasonable to spare all the confusion and pain by officially deprecating it? At the end of a day, every non-bounced hit on the “new” Dagger-Android documentation (docs were updated just three months ago!) starting now is unnecessary waste of time for some poor soul out there.
Now, if your project already uses Dagger-Android, don’t panic. There is no need to refactor anything. I’m sure it’ll continue to work. But if you start a new project today, or want to learn dependency injection to expand your toolbox, I recommend to stay clear of Dagger-Android. Learn “standard” Dagger and keep it simple. It has always been my recommendation, but now it also substantiated by Google’s announcement.
In this context many developers ask my opinion about Koin, so I’ll proactively share it.
I think that Koin is good dependency injection framework (yes, dependency injection, not service locator). In my opinion, there are two reasons why Koin got traction among Android developers. The first reason is that Koin has outstanding documentation which makes it much simpler to learn compared to Dagger. The second reason is that Koin is written in Kotlin, so it enjoyed from the early hype around Kotlin’s adoption as an official language. However, all in all, I don’t think that Koin will become mainstream in Android development.
New Dagger Documentation
As part of the announcements during Android Dev Summit, there were also a new documentaton and a new codelab for Dagger. One would hope that now, finally, Android community would get the documenation it deserves. So, I reviewed this codelab.
Unfortunately, the new codelab, in it’s current form, is a complete disaster. I know it’s a harsh statement, but it’s the appropriate one in this case. To warn as many developers as I could about the problems, I wrote this Twitter thread:
For the past two years I’ve been recommending Android devs to avoid https://t.co/2wYIaJgNVJ. Now it’s officially deprecated. Devs who listened to my advice won big time.
Today I reviewed the new official Dagger codelabs by Google. It’s a complete disaster ?♂️.
— Vasiliy Zukanov (@VasiliyZukanov) October 27, 2019
Allow me to just make something clear.
I don’t blame any googler personally for the waste associated with Dagger-Android. I don’t blame any googler personally for the awful quality of the new codelab. If I ever refer to any of them specifically, then it’s only because they are the official representatives of the company. There were two tweets in that thread that crossed the line. I was tired and got carried away. Luckily, I got called out by other devs and realized my mistake. I deleted the tweets and apologized for the mistake in real time.
Some people said I should’ve delivered the “feedback” in less publicized manner and they’d act on it. Well, I myself never experienced this magic. For many years, generations of Android developers begged Google to provide a better API for soft keyboard. It would probably be easier than most Jetpack projects, but it looks like they just don’t care about our feedback.
So, what’s left in that twitter thread, I find it appropriate. Let’s not forget that we’re talking about MILLIONS of developers around the world. Google can surely do better to avoid wasting our time again.
Future of Dependency Injection in Android
So, now you should probably learn and use “standard” Dagger without any excessive bells and whistles. But what about the future?
If you watch the aforementined talk, you’ll notice that Google already says that they have something new for us in the workings. Something that will “make Dagger in Android simpler”. Wait… this sounds familiar. Where did I hear that? Ah, yeah, I’ve been constantly hearing this for the past two years, since the first release of Dagger-Android.
From what I understood, it sounds like they are working on something that will be even more integrated into Android than Dagger-Android. That’s not a bad idea in genreal and there are frameworks which come with dependency injection out of the box (e.g. Angular). However, I’m very skeptical about yet another attempt to “make Dagger simple” by Google. I’d prefer to see them concentrating on getting the docs into good shape.
Now, I’m not saying that they are destined to fail again with this project. But I do say that chances are against them and it’s probable that they’ll screw us up, so a healthy scepticism is appropriate here. If not, I’ll be very pleased and surprised, and will extend to them my official apology.
With the effective (but not official, yet) deprecation of Dagger-Android, the landscape of dependency injection in Android became much clearer.
If you already use Dagger-Android, keep using it. It isn’t going away any time soon. If you’re not, then just pass on it. Learn and use “standard” Dagger in your app. It’s not that difficult once you understand the principles.
For example, in this video I share “my” setup. As you can see by yourself, it takes less than 30 minutes to set up all the required infrastructure in a new Android app. After that, you get the benefits.
As usual, thanks for reading, and leave your comments and questions below.