What is the best way to use Dagger if you're attempting Clean Architecture?

Viewed 184

In Clean Architecture, Robert Martin says:

It is in your Main component that dependencies should be injected by a Dependency Injection framework. Once they are injected into Main, Main should distribute those dependencies normally, without using the framework.

Martin, Robert C.. Clean Architecture (Robert C. Martin Series) (p. 232). Pearson Education. Kindle Edition.

However, Dagger doesn't work this way. Once you set up your dependencies in your application, you still need to depend on it as a framework, e.g. write @Inject annotations to get the dependencies into your classes. There is no way to 'distribute these dependencies' normally, by which I assume he means passing them through a constructor?

Can anyone help clear up my understanding and how best to use Dagger with a Clean style?

1 Answers

On Android, exactly following the advice you quoted from Robert Martin is rather difficult.

This is because there is no precise main entry point. Application, Service and Activity are quasi-entry points as your app will start with the OS instantiating one of these.

However, you don't have control over the constructor or anything really before the lifecycle callbacks. Hence, Dagger 2 on Android has had to rely on manually calling requesting a Component and calling Component#inject() inside lifecycle callbacks quasi-entry points.

However, there have been some measures to address this problem. Dagger-Android goes some way to address this by making you depend on AndroidInjector rather than some series of calls to the Application in order to retrieve the Component manually.

Even further, there is now FragmentFactory that allows control over the constructor of a Fragment, making Fragments amenable for constructor injection. If we use this then we have gone some way to following Robert Martin's advice.

To clarify the original quotation, I believe Robert Martin means that classes apart from the component root should not be polluted with logic for obtaining dependencies (e.g., by reaching into the Application, pulling out the Dagger Component). He is not prohibiting the use of the @Inject annotation which is lightweight meta-data (part of JSR-330) that simply marks a constructor as a site for injection.

In summary, yes - the current way of using Dagger 2 on Android doesn't exactly comply with Robert Martin's excellent recommendation. Nevertheless, this is a known problem and some progress has been made towards solving it.

Related