Android ViewModel and FactoryProvider: good way to manage it with Dagger Multibindings

How use ViewModelFactory with Multibindings.

--

From the past Google IO 2017 we having a new set of tools called Android Architecture Components, I have just spoken about one of them (Room) in a past article, today i want to speak about the ViewModel.

I will not write what is a ViewModel, there are many articles about it, in this article i will explain how integrate it with Dagger without boilerplate code, and how create a scalable way to manage your ViewModel Factory with Multibindings.

How it works, and what is the problem

To instantiate a ViewModel you need a ViewModelFactory: it’s a class that implements ViewModelProvider.Factory and it will create the ViewModel from a parameter .class.

when you invoke the get() method the ViewModelProvider call the create() method of the ViewModel Factory and by the class type the method return the instance of ViewModel. So if we create a new ViewModel we need to edit this class or to create a new ViewModelFactory to manage the new one.

What is the problem? If you want to use this ViewModelFactory with different ViewModels, with different constructor argument i will be obliged to pass all parameters from the ViewModelFactory, the result will be a class not scalable and very difficult to use.

The solution

In Dagger 2 exists multibindings and with it is possible to create a “map” of objects with a specific key. In our use case will be like below:

  • the key: for example the class type of ViewModel MyViewModel::class
  • the value: the instance of ViewModel MyViewModel(repository, …)

Dagger ( in compiling time) will create the map and we will provide them to ViewModelFactory as argument, so when we will invoke the create() method it will able to pick the right instance from the map:

These is the ViewModelFactory, we will create a Dagger Module to provide it:

Now to bind ViewModel and create these Map we need the multibindings and to do it we will use a specific annotation, we will call it ViewModelKey, it’s represents the key of our map.

And finally an example of Module who provides a ViewModel

The combination of Binds, IntoMap and the Target annotation (ViewModelKey) we create an entry inside our map with Key: MyViewModel::class and value MyViewModel instance.

Now we can use it inside out activity or fragment.

Conclusions

With Dagger Multibindings we can create a unique ViewModel Factory that provides all kind of ViewModel we need based from the modules inside the component.
These solution is very scalable, because if we create a new ViewModel for a new section of our application we will need only to create a Component with the same ViewModelFactoryModule and the new Module that will provide the new ViewModel.

Component with 3 ViewModels module

I hope I helped you, if you have questions please let me know!

--

--