The Android team has been increasingly vocal about their support for Dependency Injection frameworks like Dagger, going so far as to develop and recommend Hilt — their Android DI framework built on top of Dagger — for modern Android development.
In their guide to manual dependency injection the Android team lays out approaches to manual DI for View Models. They offer both the basic approach to manual DI — just instantiating everything you need in
lateinit var View Models - and the container approach using a custom
AppContainer to handle dependencies across all your Activities.
The alternative they give to this boiler-plate-heavy approach is to recommend Dagger or Hilt to handle this process for you. However, in many apps, pulling in a DI framework is overhead you really don’t need. Instead, what if there was a way to manually inject dependencies into your Android Activity & Fragment View Models without all the boiler plate?
Lazy DI Using Android Lifecycle ViewModel Extensions
One of the ways the Android Fragment & Lifecycle teams have tried to make the View Model easier to use in Activities and Fragments is providing the Android Lifecycle ViewModel Kotlin Extensions library.
This library lets you instantiate a View Model in a Fragment or Activity with a delegate method — making it easy to create a properly scoped View Model.
View Model Provider Factory
One way to enable this behavior is to use
ViewModelProvider.Factory, with which you can instantiate a View Model with it’s needed dependencies. To do so, you need to create your own Factory that extends the
ViewModelProvider.Factory interface, or create a function that can return an
object that overrides the
If we wanted to stop here, we could create a Kotlin function to do this for us:
And use it in our Activity or Fragment like this:
We can now create a View Model with the necessary dependencies! However, even with our Factory abstracted into a function, we still need to manage the boiler plate of
View Model Provider & Kotlin Extension Mashup
Remember, we could use
by viewModels or
by activityViewModels to delegate the creation of our View Models, but we weren’t able to inject our required dependencies without a Factory.
Now that we have a handy way to instantiate a View Model with a Factory, we can let these Kotlin Extensions for View Model to hide this
ViewModelProvider boiler plate. Here’s how it would look in a Fragment.
Almost perfect. All we have to do is provide a Factory and a lambda that returns our View Model. But, with a little help from the
lifecycle-viewmodel-ktx library and Kotlin extension functions, we can take it one step further.
Endgame: Easy View Model DI
Let’s use the power of extension functions, our Factory knowledge, and the
ViewModelLazy class to delegate the creation of our View Model to functions on Activity and Fragment.
We provide the function to create our View Model as a lambda that returns type
<VM : ViewModel>, and the
activityViewModelBuilder extensions do the rest.
Now, in our Activity:
We can easily build a ViewModel, along with all it’s necessary dependencies, all without the annoying boilerplate!
If you’re in a situation where you need complex Android View Models, want to follow SOLID principles of dependency injection, and you’re not quite ready to adopt the complexity of a full Dependency Injection Framework — hopefully this helps present some other options that can make the task easier to manage.
If you have thoughts on the Android View Model or want to share your approaches to manual DI, don’t hesitate to reach out @ajkueterman on Twitter, or follow me on DEV.to and leave a comment on this story.
The code from this post has been converted to a library for ease of use / maintainability. If you’d prefer just to import and go, check it out on GitHub: