Android ViewModel — Manual Dependency Injection Made Easy

Remove some boiler plate and make manual dependency injection with Android View Models easier with the power of Kotlin extensions.

AJ Kueterman
3 min readSep 28, 2020
Photo by Toan Chu https://unsplash.com/@toanchu90 on Unsplash

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 onCreateand using 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.

This is beautiful! However, what if our View Model needs to use a repositoryto make a call to Retrofit? We would like to inject that repository into our View Model when we construct it.

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 Factory.create method.

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 ViewModelProvider.

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 viewModelBuilder and activityViewModelBuilder extensions do the rest.

Now, in our Activity:

Or Fragment:

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:

https://github.com/robotsquidward/lazyviewmodels

This post was originally published on my blog ajkueterman.dev. Check out the code on GitHub.

--

--