Programming

Dependency injection in Android

I am a great fan of dependency injection in Java. I have used Guice in the past, I have used Apache Tapestry that has a great implementation of dependency injection, but Spring Boot makes DI so easy to use that it surprises me that there are still projects that don’t use it.

On Android, it’s a different story. In the old days, there was Roboguice. Roboguice was based on Google’s Guice, with additions and changes to accomodate Activity and Service classes. I loved Roboguice, but changes in Android made it harder for its developers to maintain it, until they came to the point that they stopped supporting it. I switched to using Toothpick, which I like, but as so few projects use it, I abandoned it.

I also used Robolectric, a testing framework that allows you to integrate DI into your testing.

Dagger is now the DI tool of choice on Android. Dagger requires you to explicitely inject members into activities and other classes. This is a consequence of the architecture of Android that requires extending Activity and Fragment classes. Roboguice had classes like “RoboActivity”, which became cumbersome after we had FragmentActivity, AppCompatActivity and others. Also Dagger requires module classes for configuration, which are similar to Spring Boot configuration classes. Also, you need Component interfaces to allow for DI in activities etc.

The amount of boilerplate code you need for Dagger makes me think that the old Factory pattern is easier to use than Dagger. Also, Dagger comes in versions, when you read a tutorial you need to be careful if the tutorial is actually applicable for the version of Dagger that you use.

The main trouble with DI in Android is a design flaw in Android: your activities extend the Android Activity class, rather than implement an Android Activity interface. Same for Service, Fragment, etc. Activity being an interface would make life easier for DI and for developers. It would also make testing less complicated: if you use DI in tests you need a context object that you don’t have. A few years ago you could use Robolectric that creates a fake context object for you, today you can test on a device, using the device’s context.  I use DaggerMockRule to provide an application context to a test, I have different DaggerMockRules for different types of test.

If only Android had made Activity an Interface rather than a class, we could  have used a simplified version of Spring Boot DI on Android….