# Set Up Dagger with ViewModel & Saved State Module Guide

[**Tomas Mlynaric**](https://www.strv.com/blog/authors/tomas) Android Engineer

---

A [Android Developers](https://medium.com/u/e1f26db83092?source=post_page-----44d8fa79f14----------------------) finally [@Provide](https://twitter.com/AndroidDev/status/1187437523091378176?ref=strv.ghost.io) an opinion about dependency injection, and the winner is... **Dagger**!

From my perspective, Dagger is “not great, not terrible." But it scales well and, when properly set up, you don't need to “touch” it later.  

In this article, I try to explain how to set up Dagger to work with ViewModel and SavedState module in the most universal way — set it once, use it forever.

**WARNING:**  
I’m not going to get deep into Dagger, so if you don’t know the basics of how Dagger works, please check it out first. Otherwise, the article may be tricky to understand.

**TLDR:**  
I'm sorry, this article is longer than I expected. But I wanted to explain everything with a sufficient amount of information. For those who are familiar with the details and prefer seeing working snippets only (or you're just a little lazy), skip ahead to the , at the bottom of this page.

Fasten your seatbelt! It's gonna be a rough ride.

---

*Source: Giphy, [https://gph.is/2Lhtrua](https://gph.is/2Lhtrua)*

## THE MOTIVATION

Let's start with motivation: Why do we want to do all of this?

Say you have a ViewModel `class SomeViewModel : ViewModel()`. Now, you want to fully use the power of ViewModels, so you apply inversion of control and pass dependencies to the constructor.

```kotlin
class SomeViewModel(
    private val dep1: Dependency,
    private val dep2: Dependency2
) : ViewModel()
```

If you're even more demanding, you have DI framework (Dagger in our case) do this for you. I won't describe how to set up Dagger with ViewModel, as there are many articles and SO answers available (e.g. [here](https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455?ref=strv.ghost.io) and [here](https://stackoverflow.com/questions/54347924/inject-property-into-viewmodel-using-dagger-2/54353028?ref=strv.ghost.io#54353028)).

```kotlin
class SomeViewModel @Inject constructor(
    private val depFromDagger1: Dependency,
    private val depFromDagger2: Dependency2
) : ViewModel()
```

Still want more? Outrageous! Say you actually want to pass something besides dependencies coming from DI graph. Something like `Bundle`, or just some variable like `articleId`.

What are your options?

You can instantiate your ViewModel with dependencies from the graph and set your custom variable manually after construction with either `lateinit var` or with `var` of *nullable* type.

```kotlin
class SomeViewModel @Inject constructor(
    private val depFromDagger2: Dependency2
) : ViewModel() {
    // may crash with UninitializedPropertyAccessException
    lateinit var articleId: String
    // must !! or ?. for every access
    var fragmentParams: Bundle? = null
}
```

Neither one of these is great because they make your code more fragile. What if you reuse your ViewModel in another screen and forget to set the dynamic parameters? Crash! ...Or an improperly initialized class. And in case of a *nullable* variable, either you force `!!` it, or you have unnecessary null checks in your code.

Another option is to leave Dagger out of the game, create a custom ViewModel factory, and manually pass dependencies which will be injected into Fragment or Activity.

```kotlin
class SomeViewModel(
    private val dep2: Dependency2,
    private val articleId: String
) : ViewModel() {
    class Factory (
        private val articleId: String
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return SomeViewModel(dep1, dep2, articleId) as T
        }
    }
}
```

In Fragment, you need to `@Inject` the dependencies and pass it to the factory.

```kotlin
class SomeFragment : Fragment() {
    // inject into this class omitted for brevity
    @Inject
    lateinit var dep1: Dependency
    lateinit var dep2: Dependency
    lateinit var viewModel : SomeViewModel
    
    override fun onCreate(savedState: Bundle?) {
        super.onCreate(savedState)
        // retrieve articleId and pass it to your factory
        val articleId = arguments!!.getString("article_id")
        val factory = SomeViewModel.Factory(dep1, dep2, articleId)
        viewModel = ViewModelProvider(this, factory).get(SomeViewModel::class.java)
    }
}
```

This works, but it’s so much boilerplate. With each added, changed or removed dependency, you have to update three places in your code:

- ViewModel’s constructor
- ViewModel's custom factory
- Instantiation of the factory with injected dependencies

*(Un)fortunately, this is (probably) exactly what we want to achieve without all of the boilerplate, because we want to use one dynamically retrieved parameter — **SavedStateHandle**, from Saved State Module library.*

---

## VIEWMODEL AND ONSAVEINSTANCESTATE()

Before we dive into Saved State module, let's recap ViewModel's strengths and weaknesses.

ViewModel is great at handling orientation changes, as it survives when Fragment or Activity is destroyed. This lets you keep doing any long action without leaking the screen or needing to “restart” the action.

On the other hand, when you put your app into the background and the Android system kills it (usually due to longer inactivity and a need for more resources), the state of ViewModel is not preserved. What's worse, Fragment or Activity will handle this use case by calling `onSaveInstanceState(outState: Bundle)`, but your ViewModel has no information about it. You need to handle this yourself by taking data from ViewModel and saving it in Fragment/Activity and later restoring it by manually placing it into ViewModel. But as I showed you earlier, this makes your ViewModel less robust because you can't run actions from constructor.

### ViewModel doesn’t handle saving/restoring state.

The truth is, many apps don’t even bother solving this issue, which leads to weird behavior or even crashing when the user opens the app after some inactivity.

However, there's light at the end of the tunnel.

---

## SAVED STATE MODULE FOR VIEWMODEL

[Saved State Module for ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate?ref=strv.ghost.io) is the new AndroidX library that allows handling instance state from ViewModel without any difficulty. This library provides custom factory for creating ViewModels. ViewModel constructor then expects `SavedStateHandle` parameter, which it communicates with. Destruction (and saving instance state) of a Fragment/Activity is then reflected in the handle, and ViewModel can therefore save or restore its state without the help of other classes.

---

## SO HOW TO USE IT?

### 0.

Add gradle dependency.

```gradle
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-rc03"
```

### 1.

Get the ViewModel with SavedStateViewModelFactory factory. You may also specify some default arguments to be passed into ViewModel. This parameter in the constructor is `SavedStateRegistryOwner`, which is either Fragment or Activity and serves as a reference for saving/restoring the instance state.

```kotlin
class SomeFragment : Fragment() {
    // default arguments, so you can set something dynamically
    val defaultArgs: Bundle? = bundleOf("id" to 5) // may be null

    // default factory for ViewModel creation
    val factory = SavedStateViewModelFactory(application, this, defaultArgs)

    // get the ViewModel with the factory and scope you want
    viewModel = ViewModelProvider(this, factory)[SomeViewModel::class.java]
}
```

### 2.

In your ViewModel’s constructor, have a variable of type `SavedStateHandle`, which serves as a handler for saving or retrieving data. If you passed any default arguments, they will be part of this handle.

```kotlin
class SomeViewModel(
    private val application: Application,
    private val savedStateHandle: SavedStateHandle
) {
    // ...
}
```

The handle has set/get methods similar to `Bundle` which, in case of ViewModel being killed by the system, are safely stored in app's state and restored later. It also has `getLiveData(key)` method, which returns `MutableLiveData` to simplify working with UI.

In the example below, `counter` value is retrieved in ViewModel's `init{}`. If value is not set, `null` is returned. Method `onPlusClick()` changes `counter` LiveData. In the end, you observe the LiveData and set current value into the handle, which will be safely stored.

```kotlin
class SomeViewModel(/* ..omitted.. */) {
    val counter = MutableLiveData<Int>(0)

    init {
        counter.value = savedStateHandle.get("counter") ?: 0
        counter.observeForever { newValue ->
            savedStateHandle.set("counter", newValue)
        }
    }

    fun onPlusClick() {
        counter.value = (counter.value ?: 0) + 1
    }
}
```

You can also simplify it by using `getLiveData(key, defaultValue)` method, which results in the same functionality with less code.

```kotlin
class SomeViewModel(/* ..omitted.. */) {
    val counter = savedStateHandle.getLiveData("counter", 0)
}
```

This way, when system kills your app, you can be sure that ViewModel will save and restore its state properly without the help of Fragment/Activity class.

---

## HOW TO TEST THE SYSTEM KILLING YOUR APP?

With all this information, you're probably thinking: How do I know if it actually works? You often don’t want to sit and wait until the Android system kills your app in the background; you want to test it reasonably. There are two easy options that let you simulate the behavior:

**a. Set the background process limit to none:**  
On your device, go to *Settings* ➡ *Developer options* ➡ *Background process limit* ➡ set to **No background processes**

**or**

**b. Kill your app with adb:**  
- Put your app into background (if you don’t do this step, `adb` will kill the app anyway, but the system won’t save the instance state).  
- Use the `adb` command from snippet to kill your package. Small shell script may help to kill it for you and save some time.

```bash
#!/bin/bash
# Provide package of your application (com.example.myapp)
PACKAGE=$1

# First, put your app to background and then run this script
echo "Killing $PACKAGE"
adb shell ps | grep $PACKAGE | awk '{print $2}' | xargs adb shell run-as $PACKAGE kill
```

Alright, so — in the first section, we saw how to connect Dagger • ViewModel dot. This section described how to connect ViewModel • SavedStateHandle dot.  
The question now is, how do we connect all the dots? How do we use Dagger and ViewModel with SavedStateHandle?

---

## DAGGER AND VIEWMODEL WITH SAVEDSTATEHANDLE

As we know now, for ViewModel we can either have custom Factory which manually passes parameters, or fully Dagger-controlled instantiation. In our case, we would like to have a bit of both worlds.

Let's go over what sorcery needs to be done to connect the dots.

### @AssistedInject for the win

Unfortunately, we cannot do it without some help—a hack, so to speak. We need to introduce a way to keep injecting Dagger-related dependencies (a `Repository` or application `Context` or something similar), while also having some of the parameters injected manually.

See how AssistedInject works [here](https://github.com/square/AssistedInject?ref=strv.ghost.io).

Fortunately, this is exactly what AssistedInject library does. It allows you to annotate the constructor of your class with `@AssistedInject` (in our case, ViewModel) and your dynamic parameters with `@Assisted` (in our case, `SavedStateHandle`). Based on this information, the library generates a Factory compatible with Dagger for instantiation of your class. The factory has `@Inject` constructor with all dependencies from your ViewModel constructor and one method with the dynamic parameters marked with `@Assisted`.

*(You can listen to [Jake Wharton](https://medium.com/u/8ddd94878165?source=post_page-----44d8fa79f14----------------------)'s talk, [Helping Dagger Help You](https://jakewharton.com/helping-dagger-help-you/), where he describes it more in depth.)*

---

## HOW TO SET UP ASSISTEDINJECT WITH SAVEDSTATEHANDLE?

Let’s start with the setup.

### 0.

Add gradle dependency.

```gradle
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.2'
```

Version *0.5.2* indicates, that it may not be extra mature, but for our use case it works fine. Since the library only generates Dagger code, you shouldn’t see unstable code during execution (worst case, there may be issues with building).

### 1.

Create **base** interface which has one `create(savedStateHandle: SavedStateHandle): T` method. The generic parameter `T` informs AssistedInject about what type of ViewModel it should generate. This interface allows us to omit repetitive code in each ViewModel, and is needed because we will add all assisted factories to one `@Multibinds` map.

```kotlin
/**
 * Base interface for all ViewModel factories
 */
interface AssistedSavedStateViewModelFactory<T : ViewModel> {
    fun create(savedStateHandle: SavedStateHandle): T
}
```

### 2.

Instead of `@Inject`, use `@AssistedInject` annotation. `SavedStateHandle` parameter is annotated with `@Assisted`. This way, the library knows which parameters are provided via Dagger and which are provided dynamically.

```kotlin
class SomeViewModel @AssistedInject constructor(
    @Assisted private val savedStateHandle: SavedStateHandle
) {
    // ...
}
```

### 3.

**Inside** the ViewModel class, add interface annotated with `@AssistedInject.Factory`, which extends the **base** interface specified earlier — `AssistedSavedStateViewModelFactory<T>`.

```kotlin
class SomeViewModel @AssistedInject constructor(
    // must be inside of the ViewModel class!
    @AssistedInject.Factory
    interface Factory : AssistedSavedStateViewModelFactory<SomeViewModel> {
        override fun create(savedStateHandle: SavedStateHandle): SomeViewModel // may be omitted prior to Kotlin 1.3.60 or after PR #121 in AssistedInject lib
    }
}
```

AssistedInject will generate class `SomeViewModel_AssistedFactory`, which implements the `Factory` interface. It will include Dagger-related variables (`Provider<*>`) in its constructor and implement the `create(savedStateHandle: SavedStateHandle)` method.

**Side note:**  
In Kotlin 1.3.60+ you need to override `create()` due to a bug — the superclass uses the wrong argument name, which AssistedInject doesn't expect. You can override it as shown or check the [issue](https://github.com/square/AssistedInject/issues/81?ref=strv.ghost.io#issuecomment-529352366). There's also [PR](https://github.com/square/AssistedInject/pull/121?ref=strv.ghost.io) to fix argument names.

### 4.

Create Dagger `@Module`, mark it with `@AssistedModule`, and include `AssistedInject_NameOfTheModule::class`. The generated module will be created after building.  

This module contains `@Binds` methods from generated ViewModel factories to their implementations (so you can inject your interface).

Inside your module class, specify all ViewModels participating in this injection. Instead of binding `SomeViewModel` parameter with `@Binds` to `ViewModel`, you **must bind the factory to its base class** (`SomeViewModel.Factory` to `AssistedSavedStateViewModelFactory<out ViewModel>`). You need to do this for each ViewModel.

```kotlin
@AssistedModule
@Module(includes = [AssistedInject_BuilderModule::class])
abstract class BuilderModule {
    @Binds
    @IntoMap
    @ViewModelKey(SomeViewModel::class)
    abstract fun bindVMFactory(f: SomeViewModel.Factory): AssistedSavedStateViewModelFactory<out ViewModel>
}
```

### 5.

As with regular Dagger and ViewModel injection, you need a custom factory and bindings in a map (`@Multibindings`). For SavedState, AndroidX provides `AbstractSavedStateViewModelFactory`, which has a `create()` method with `SavedStateHandle`. The idea is to create an *abstract factory* (a factory that creates factories), so in your Fragment/Activity, you can call `create()` and pass dynamic parameters like `defaultArguments` (Bundle) and `this` (SavedStateRegistryOwner).

```kotlin
@Reusable
class InjectingSavedStateViewModelFactory @Inject constructor(
    private val assistedFactories: Map<Class<out ViewModel>, @JvmSuppressWildcards AssistedSavedStateViewModelFactory<out ViewModel>>
) {
    fun create(owner: SavedStateRegistryOwner, defaultArgs: Bundle? = null): AbstractSavedStateViewModelFactory {
        return object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
            @Suppress("UNCHECKED_CAST")
            override fun <T : ViewModel?> create(
                key: String,
                modelClass: Class<T>,
                handle: SavedStateHandle
            ): T {
                // Attempt to get ViewModel from assisted inject factories
                assistedFactories[modelClass]?.let {
                    try {
                        return it.create(handle) as T
                    } catch (e: Exception) {
                        throw RuntimeException(e)
                    }
                } ?: throw IllegalArgumentException("Unknown model class $modelClass")
            }
        }
    }
}
```

### 6.

In your Fragment, `@Inject` the `InjectingSavedStateViewModelFactory` and use it to retrieve your ViewModel.  

```kotlin
class SomeFragment : Fragment() {
    // ...
    lateinit var abstractFactory: InjectingSavedStateViewModelFactory
    lateinit var viewModel: SomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val defArgs = bundleOf("id" to 5) // may be null
        // create factory for Dagger
        val factory = abstractFactory.create(this, defArgs)
        // retrieve ViewModel
        viewModel = ViewModelProvider(this, factory)[SomeViewModel::class.java]
    }
}
```

You may also inject this factory in your `BaseFragment` to avoid boilerplate in each Fragment.

---

## WANT TO ADD THIS TO AN EXISTING PROJECT?

This is intended for existing projects with Dagger and “plain” ViewModels, aiming to incorporate SavedState support. Not all ViewModels need to use SavedState, so you can reduce boilerplate by selectively adopting assisted injection.

In usual Dagger + ViewModel setup, your classes are bound in a map of `Class<out ViewModel>` to `Provider<ViewModel>`. This map is injected into your ViewModel factory, which handles instantiation.

```kotlin
Map<Class<ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
```

In AssistedInject, you tweak this structure: you need a map of **ViewModel class** to **AssistedSavedStateViewModelFactory**.

```kotlin
Map<Class<out ViewModel>, @JvmSuppressWildcards AssistedSavedStateViewModelFactory<out ViewModel>>
```

You can inject both structures and your multi-purpose factory will attempt to instantiate ViewModels via each method, falling back or crashing if unsuccessful.

```kotlin
@Reusable
class InjectingSavedStateViewModelFactory @Inject constructor(
    private val assistedFactories: Map<Class<out ViewModel>, @JvmSuppressWildcards AssistedSavedStateViewModelFactory<out ViewModel>>,
    private val viewModelProviders: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<out ViewModel>>
) {
    fun create(owner: SavedStateRegistryOwner, defaultArgs: Bundle? = null): ViewModel {
        return object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
            override fun <T : ViewModel?> create(
                key: String,
                modelClass: Class<T>,
                handle: SavedStateHandle
            ): T {
                val viewModel = createAssistedInjectViewModel(modelClass, handle)
                    ?: createInjectViewModel(modelClass)
                    ?: throw IllegalArgumentException("Unknown model class $modelClass")
                return viewModel as T
            }

            private fun <T : ViewModel?> createAssistedInjectViewModel(
                modelClass: Class<T>,
                handle: SavedStateHandle
            ): ViewModel? {
                val creator = assistedFactories[modelClass] ?: assistedFactories.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
                return creator?.create(handle)
            }

            private fun <T : ViewModel?> createInjectViewModel(modelClass: Class<T>): ViewModel? {
                val creator = viewModelProviders[modelClass] ?: viewModelProviders.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
                return creator?.get()
            }
        }
    }
}
```

---

## TLDR

For those who want to skip the detailed article, here are the key steps:

1. Add gradle dependency:

```gradle
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.2'
```

2. Update your ViewModel with AssistedInject:

```kotlin
class SomeViewModel @AssistedInject constructor(
    @Assisted private val savedStateHandle: SavedStateHandle
) {
    // ...
}
```

3. Create or update your Dagger module with `@AssistedModule`, include generated module `AssistedInject_MyDaggerModule::class`, and bind your ViewModel factories:

```kotlin
@AssistedModule
@Module(includes = [AssistedInject_BuilderModule::class])
abstract class BuilderModule {
    abstract fun bindVMFactory(f: SomeViewModel.Factory): AssistedSavedStateViewModelFactory<out ViewModel>
}
```

4. Make or update your ViewModel factory (`InjectingSavedStateViewModelFactory.kt`) — see [gist](https://gist.github.com/mlykotom/c2b528e1f9a2ca1039ad5e992308ccb2?ref=strv.ghost.io).

5. Retrieve your ViewModel using this factory in your Fragment.

---

## CONCLUSION

In this article, I showed how to set up Dagger with ViewModels and the Saved State module in a mostly boilerplate-less way. Initially, it's boilerplate-heavy, but afterward, adding each ViewModel is straightforward.

You can even retrofit existing projects with minimal effort.

A sample project with an Activity, Fragment, and two ViewModels (one with `@Inject`, one with `@AssistedInject`) is available: [https://github.com/mlykotom/connecting-the-dots-sample?ref=strv.ghost.io](https://github.com/mlykotom/connecting-the-dots-sample?ref=strv.ghost.io)

---

## REFERENCES

The articles that led me here, each describing a “dot” to connect:

- [Saving UI state with ViewModel, SavedState, and Dagger](https://proandroiddev.com/saving-ui-state-with-viewmodel-savedstate-and-dagger-f77bcaeb8b08?ref=strv.ghost.io)
- [Brave new Android world with AssistedInject](https://proandroiddev.com/brave-new-android-world-with-assistedinject-d11bdc20147d?ref=strv.ghost.io)
- [How to produce SavedStateHandle in your ViewModel](https://www.coroutinedispatcher.com/2019/08/how-to-produce-savedstatehandle-in-your.html?ref=strv.ghost.io)

Thanks to everyone who reviewed this article, especially [Marek Abaffy](https://medium.com/u/2648e51c9617?source=post_page-----44d8fa79f14----------------------), [Michal Urbanek](https://medium.com/u/29a315899171?source=post_page-----44d8fa79f14----------------------), and [Iveta Jurčíková](https://medium.com/u/177a4c6dcd67?source=post_page-----44d8fa79f14----------------------).  

---

**Don't miss anything**