Android ViewModel: Manual Dependency Injection Made Easy
Tags: android, kotlin, tutorial
Published: 2020-09-28 17:29:12

---
title: Android ViewModel: Manual Dependency Injection Made Easy 
published: true
description: Remove some boiler plate and make manual dependency injection with Android View Models easier with the power of Kotlin extensions.
tags: android, kotlin, tutorial
cover_image: https://images.unsplash.com/photo-1595131264266-6804a61cb738?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3750&q=80
---

If you want to go right to a library that enables easy View Model dependency injection, check out [Lazy ViewModels](https://github.com/robotsquidward/lazyviewmodels) on [my GitHub](https://github.com/robotsquidward)

---

The Android team has been increasingly vocal about their support for [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) frameworks like [Dagger](https://dagger.dev/), going so far as to develop and recommend [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) - their Android DI framework built on top of Dagger - for modern Android development.

In their guide to [manual dependency injection](https://developer.android.com/training/dependency-injection/manual) 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 `onCreate` and 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](https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-viewmodel-ktx) library. 

```groovy
dependencies { 
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
}
```

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.

```kotlin
class MyActivity : AppCompatActivity() {

    private val model: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}
```

This is beautiful! However, what if our View Model needs to use a [repository](https://developer.android.com/jetpack/guide#overview) to make a call to [Retrofit](https://square.github.io/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`](https://developer.android.com/reference/androidx/lifecycle/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:

```kotlin
fun createWithFactory(
  create: () -> ViewModel
  ): ViewModelProvider.Factory {
    return object : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
            return create.invoke() as T
        }
    }
}
```

And use it in our Activity or Fragment like this: 

```kotlin
private val model: MyViewModel by lazy {
  ViewModelProvider(
    this, 
    createWithFactory {
        MyViewModel(repo = MyRepository())
    }
  ).get(MyViewModel::class.java)
}
```

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.

```kotlin
private val model: MyViewModel by activityViewModels {
    createWithFactory {
        MyViewModel(repo = MyRepository())
    }
}
```

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.

```kotlin
/**
 * Get a [ViewModel] in an [ComponentActivity].
 */
@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModelBuilder(
    noinline viewModelInitializer: () -> VM
): Lazy<VM> {
    return ViewModelLazy(
        viewModelClass = VM::class,
        storeProducer = { viewModelStore },
        factoryProducer = {
            return@ViewModelLazy object : ViewModelProvider.Factory {
                override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                    @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
                    return viewModelInitializer.invoke() as T
                }
            }
        }
    )
}

/**
 * Get a [ViewModel] in a [Fragment].
 */
@MainThread
inline fun <reified VM : ViewModel> Fragment.activityViewModelBuilder(
    noinline viewModelInitializer: () -> VM
): Lazy<VM> {
    return ViewModelLazy(
        viewModelClass = VM::class,
        storeProducer = { requireActivity().viewModelStore },
        factoryProducer = {
            object : ViewModelProvider.Factory {
                override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                    @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
                    return viewModelInitializer.invoke() as T
                }
            }
        }
    )
}
```

Now, in our Activity:

```kotlin
private val model: MyViewModel by viewModelBuilder {
    MyViewModel(repo = MyRepository())  
}
```

Or Fragment:

```kotlin
private val model: MyViewModel by activityViewModelBuilder {
    MyViewModel(repo = MyRepository())  
}
```

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](https://twitter.com/ajkueterman) on Twitter, or follow me on [DEV.to](https://dev.to/robotsquidward) and leave a comment on this story.

---

This story was originally published on my blog, at [ajkueterman.dev](https://ajkueterman.dev/posts/android-viewmodel-manual-dependency-injection-made-easy/)