Clean Android Application class with Dependency Injection: AppInitializers

If you’re developing an Android app, you’re going to have a special guest in your codebase: the Application
class.
As your app grows, it’s very likely that more libraries require some kind of initialization in the Application class with the purpose of preparing its usage throughout the app, making it difficult to maintain and scale.
According to Android documentation, the responsibility of the Application class is to maintain the global application state.
So, how can we keep this class focused on this single responsibility?
Breaking initializers into classes.
So, let’s start by moving each initialization block to a class. Any initialization will require the application instance to complete its creation, so let’s create a straightforward interface that our initialization classes will implement:
Perfect! Now, start implementing it. Below you can see an example of the Stetho initialization block:
Ok cool! After doing this refactoring work, you’ll end up with one class per initialization block. A quick look to the container package will tell you what your app needs to initialize!

This looks nice but… How can we run all these initializers with no pain?
Dagger2 Multibindings to the rescue!
So let’s use Dagger and one of its powerful features: Multi bindings.
Create a dagger module, and declare all your AppInitializer
implementations there.
With @IntoSet
you’re telling Dagger that that AppInitializer
dependency will collaborate in a Set
if you decide to inject it.
So, when injecting a Set<AppInitializer>
Dagger will fill it with all @IntoSet
annotated app initializer providers you have declared in your module(s).
So, let’s wrap the initialization execution into a class, that just iterates through the initialization classes and runs them:
Amazing! Now, let’s inject our brand new AppInitializers
class:
Main benefits
Now, thanks to Dagger, your app initialization is part of your dependency graph. You can use the power of Dagger to do some cool stuff, like replacing your dependencies based on your needs. This is even more interesting if you have your app covered by UI test.
Usually, some of the libraries we use in production / debug don’t need to be initialized for running tests. By just creating an alternative dagger module that excludes these unneeded libraries from our AppInitializers
set, we’ll prevent them to run their initialization logic.
Additionally, we can customize our AppInitializer
class to specify any conditions required for each initializer to run. For example, some libraries can run the initialization block in a background thread, some of them are required to complete the initialization to continue with the app creation, etc. Just extend the interface to request these conditions from its implementations.

Thanks to Chris Banes and his awesome showcase of Android architecture in Tivi, where the original idea of AppInitializers
comes from!