Dagger Useful Techniques — #1 Map Multibindings

20 Aug 2018

android  ]

Welcome to a series of Dagger Useful Techniques to make your dependency injection experience smoother. In this series, I would like to help the developers to make the most of Dagger who are using it for dependency injection. But before I start, there are something to clarify.

This article is all about dagger techniques, not about how one can implement dagger for dependency injection. I assume that you are already familiar with the basics of dependency injection using dagger. Although I am sharing some link which will be helpful if you are new to dependency injection and want to use dagger —

This is the Part 1 of this series.

Map Multibindings

The beauty of Dagger is the annotations. We all love annotations because annotations can be interpreted at compile time by the IDE or compiler or at run-time by the framework. Dagger uses annotation to generate lots of code for you which is used for injection.

According to the official docs of dagger —

Dagger lets you use multibindings to contribute entries to an injectable map as long as the map keys are known at compile time.

To contribute an entry to a multibound map, add a method to a module that returns the value and is annotated with @IntoMap and with another custom annotation that specifies the map key for that entry. To contribute an entry to a qualified multibound map, annotate each @IntoMap method with the qualifier.

Then you can inject either the map itself (Map<K, V>) or a map containing value providers (Map<K, Provider>). The latter is useful when you don’t want all of the values to be instantiated because you’re going to extract one value at a time, or because you want to get a potentially new instance of each value each time you query the map.

The above description looks very theoretical (but I recommend you to read it and try to understand) and you are wondering what is the need of doing all this if we can directly inject different components. So let me explain this by an example. Look at the screenshot below —

Screenshot of Google Assistance App

As you can clearly see, there are different view types like text_message type, image_message type and information_message type. These all can be implemented using different types of viewholder. Here the Map Multibinding can play an important role which let you return particular viewholder corresponding to a message type. The advantage of this approach, it provides viewholder at compile time so you can ensure whether a correct viewholder is returning or not and this is also simplifies injection of view holders (I will explain later how).

Sample Code

(Read the above contents from official doc, follow line by line and try to relate that content with the following implementation)

Instead of using custom MapKey, you can use default keys provided by dagger — @StringKey, @IntKey, @LongKey, @ClassKey. More info here

@Binds is a drop in replacement for Provides methods which simply return an injected parameter. Prefer @Binds because the generated implementation is likely to be more efficient.

Now you can inject this like below —

This will simplify the injection of Viewholder by just adding a single method to ViewholderModule. There are some other concepts related to multibinding in dagger about which you can read here.

Final Words

That’s all about Map Multibindings. Although there is a lot to say about multibinding but I would like you to check the docs and try to figure out which suits you best. I have not mentioned about how injection works in dagger or how to connect module (ViewHolderModule in above case) to component because I assumed that you have a basic familiarity about dagger. In next part, I will describe techniques available in new Dagger 2.11 which simplifies the injection a lot easier.

I hope you have enjoyed reading this article. You can find source code which has above implementation here — Click Here. Check my github profile for other sample projects — https://github.com/amitkma

Next post: What is Kotlin and Why should you use it?