While Multibinding is an alternative, it’s unnecessarily complex
Disclaimer
With Dagger Hilt, you don’t need this anymore since the ViewModel Factory is handled by Hilt’s magic under the hood. However, if you can’t migrate your legacy code to Hilt or soon or simply prefer plain Dagger (2), this will save you a lot of work.
The ViewModel and the Generic ViewModel Factory
The Usage
Explanation
The ViewModel is constructed and available in Dagger’s object graph through the @Inject constructor
annotation.
Now the only thing the factory needs to do is to grab the ViewModel from the object graph
class WeatherViewModelFactory @Inject constructor(private val provider: Provider<WeatherViewModel>)
(Factory patterns implies a scope so Provider is used here to prevent accidental scoping;
I learned this from an excellent Dagger course by Vasiliy Zukanov on Udemy;
The difference between Lazy<>
and Provider<>
wrappers are still unclear to me at this point. My current believe is that it should not matter for most ViewModels)
Dagger-powered ViewModel Factory with Generic Type
Now if we simply applies generic type T: ViewModel
to the above ViewModel Factory, we would end up with a reusable GenericViewModelFactory!
Open questions
It’s unclear to me why the Internet is full of tutorials showing the Multibinding method (including Vailiy’s course, interestingly). My testing so far has not revealed any problem (yes, the ViewModel does not get recreated on device rotation 😎)
If you know any drawbacks of this method, I would love to hear 🙏
P.S.: full source code in a working app can be found here