Image for post
Image for post

Activities Subcomponents Multibinding in Dagger 2

Mirek Stanek
Oct 19, 2016 · 4 min read

A couple months ago, during MCE³ conference, Gregory Kick in his presentation showed a new concept of providing Subcomponents (e.g. to Activities). New approach should give us a way to create ActivitySubcomponent without having AppComponent object reference (which used to be a factory for Activities Subcomponents).
To make it real we had to wait for a new release of Dagger: version 2.7.

The problem

Before Dagger 2.7, to create Subcomponent (e.g. which is Subcomponent of ) we had to declare its factory in parent Component:

Thanks to this declaration Dagger knows that has access to dependencies from .

Having this, injection in looks similar to:

The problems with this code are:

  • Activity depends on (returned by — whenever we want to create Subcomponent, we need to have access to parent Component object.
  • has to have declared factories for all Subcomponents (or their builders), e.g.:
    .

Modules.subcomponents

Starting from Dagger 2.7 we have new way to declare parents of Subcomponents. annotation has optional field which gets list of Subcomponents classes, which should be children of the Component in which this module is installed.

Example:

is installed in . It means that both: and are Subcomponents of .
Subcomponents declared in this way don’t have to be declared explicitly in (like it was done in first code listing in this post).

Activities Multibinding

Let’s see how we could use to build Activities Multibinding and get rid of AppComponent object passed to Activity (it’s also explained at the end of this presentation). I’ll go only through the most important pieces in code.
Whole implementation is available on Github: Dagger2Recipes-ActivitiesMultibinding.

Our app contains two simple screens: and . We want to be able to provide Subcomponents to both of them without passing object.

Let’s start from building a base interface for all Activity Components builders:

Example Subcomponent: could look like this:

Now we would like to have of Subcomponents builders to be able to get intended builder for each Activity class. Let’s use Multibinding feature for this:

is installed in . Like it was explained, thanks to this and will be Subcomponent of .

Now we can inject of Subcomponents builder (e.g. to class):

To have additional abstraction we created interface (because of builders doesn’t have to be injected into class):

And the final implementation of injection in Activity class:

It’s pretty similar to our very first implementation, but as mentioned, the most important thing is that we don’t pass object to our Activities anymore.

Example of use case — instrumentation tests mocking

Besides loose coupling and fixed circular dependency (Activity <-> Application) which not always is a big issue, especially in smaller projects/teams, let’s consider the real use case where our implementation could be helpful — mocking dependencies in instrumentation testing.

Currently one of the most known way of mocking dependencies in Android Instrumentation Tests is by using DaggerMock (Github project link). While DaggerMock is powerful tool, it’s pretty hard to understand how it works under the hood. Among the others there is some reflection code which isn’t easy to trace.

Building Subcomponent directly in Activity, without accessing AppComponent class gives us a way to test every single Activity decoupled from the rest of our app.
Sounds cool, now take a look at code.

Application class used in our instrumentation tests:

Method gives us a way to replace implementation of ActivityComponentBuilder for given Activity class.

Now take a look at our example Espresso Instrumentation Test:

Step by step:

  • We provide Mock of and all dependencies which have to be mocked (just in this case). Our mocked returns custom implementation of which injects (with mocked object in it).
  • Then our replaces the original Builder injected in (line 28):
  • Finally test — we mock method. Injection process happens when Activity is created (line 36): and at the and we’re just checking the results with Espresso.

And that’s all. As you can see almost everything happens in class and the code is pretty simple and understandable.

Source code

If you would like to test the implementation on your own, source code with working example showing how to create Activities Multibinding and mock dependencies in Instrumentation Tests is available on Github: Dagger2Recipes-ActivitiesMultibinding.

Thanks for reading!

AzimoLabs

We’re the tech team behind Azimo — the faster, cheaper way…

Thanks to Bartosz Grzybowski

Mirek Stanek

Written by

Tech Lead at @Azimo. I dream big 🌌 🔭 and build technology for people 💻 💚 👫. Creator of PrzywodztwowIT.pl (🇵🇱 Polish newsletter about leadership).

AzimoLabs

AzimoLabs

We’re the tech team behind Azimo — the faster, cheaper way to send money internationally.

Mirek Stanek

Written by

Tech Lead at @Azimo. I dream big 🌌 🔭 and build technology for people 💻 💚 👫. Creator of PrzywodztwowIT.pl (🇵🇱 Polish newsletter about leadership).

AzimoLabs

AzimoLabs

We’re the tech team behind Azimo — the faster, cheaper way to send money internationally.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store