Dagger Multibindings for Android (Part 1)
I was actually not too excited about it when I first heard about the multibindings feature from Dagger. But as it now gave me the motivation to write my first blog post ever, you can already guess that I changed my mind about it.
Let me first give you an overview what multibinding is. With Dagger you usually define how to provide single objects. But if you want to provide a whole collection of objects, multibinding comes into play. For example if you have a bunch of shapes.
You can inject all those shapes together in one Set via Dagger multibindings.
This simple technique has many interesting use cases. In the documentation they give a hint what it can potentially be used for.
… Dagger assembles the collection so that application code can inject it without depending directly on the individual bindings. You could use multibindings to implement a plugin architecture, for example, where several modules can contribute individual plugin interface implementations so that a central class can use the entire set of plugins …
This plugin architecture sounds interessting right ? It’s something we like to achieve when writing software. There are already multiple principles which advise us to use such a plugin architecture. One of those, which can be nicely implemented with multibinding, is the open-closed principle:
software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification
Let’s see how mutlibinding helps us to follow this principle with a simplified example from my previous project #ShareTheMeal. We were in the process of switching to another payments solution, so it was a good opportunity to refactor some code. We had several payment providers like PayPal, Google Pay, credit card, etc and we knew all of them would be used for one thing: to pay (or in our case to donate). It became clear for us, that this is a good use case for polymorphism and we created the following interface.
Next we implemented the interface for our different payment providers. Some of them like Google Pay were only enabled for certain users, so we added also a method to check this.
We put all our payment providers via multibindings in a map like this
Our logic was quite straightforward. We displayed all the enabled payment providers to the user. When the user decided to use one of the payment methods for his donation, we identified it via the map key and called the pay function.
With this setup we could easily add or remove new payment providers without changing the existing code and therefore fulfilled the open-closed principle. We just had to update the multibindings map via Dagger. In the context of plugin architecture you could say each payment provider was a plugin for us.
In our case it worked out very well, but be aware when to use it. In general the open-closed principle is easy to apply when you know about the upcoming functionality, but unfortunately you can never be sure what will come next. Nevertheless we were very confident that the number of functions of our payment providers would stay small and stay the same for each of them.
For the next parts I would like to show some more Android specific use cases for multibindings like ViewModelFactory, Adapter Delegates, Activity Behaviours. So stay tuned and thank you for reading. As this is my first blog post, feedback would be highly appreciated. Also, feel free to connect with me.