Dagger-Dot-Android Part 2: ViewModels and ViewModel Factories
Tags: android, kotlin, dagger, viewmodel
Published: 2018-04-30 17:16:55

---
title: Dagger-Dot-Android Part 2: ViewModels and ViewModel Factories
published: true
description: Using ViewModels to manage the lifecycle of objects creating with Dagger
tags: android, kotlin, dagger, viewmodel
cover_image: https://i.imgur.com/UC5y8yO.jpg
---

_(no, not those kind of factories)_

1. [Part 1 — Basic Setup](https://dev.to/autonomousapps/the-daggerandroid-missing-documentation-33kj)
2. This part
3. [Part 3 — Fragments](https://dev.to/autonomousapps/the-daggerandroid-missing-documentation-part-3-fragments-12go)

If you read the [first part](https://dev.to/autonomousapps/the-daggerandroid-missing-documentation-33kj) of this tutorial, then you already know the basics of how to set up a project that uses the [dagger.android](https://google.github.io/dagger/android) package, Google's (relatively) new take on Dagger and Android. You know the basics of injecting an `Activity`, and you know how to replace your app's production objects with test doubles to make instrumentation testing a breeze (relatively speaking...).

Now in Part 2, we're going to learn how to use [ViewModels](https://developer.android.com/topic/libraries/architecture/viewmodel) and [LiveData](https://developer.android.com/topic/libraries/architecture/livedata), from the [Android Architecture Components](https://developer.android.com/topic/libraries/architecture/), to manage the lifecycle of our Dagger-provided objects.

# Setup

Add the following to your `app/build.gradle` file:
```groovy
dependencies {
  // ...all the libs...
  implementation "android.arch.lifecycle:extensions:1.1.1"
}
```
As you can see, we're just adding a single dependency. This one gives us access to both `ViewModel` and `LiveData` (and friends). Now, let's use these classes for managing the state of our "View", represented by our activity.

# `MainActivity`

This is very similar to what we saw in [Part 1](https://dev.to/autonomousapps/the-daggerandroid-missing-documentation-33kj). New section are called out with comments.

```kotlin
class MainActivity : AppCompatActivity() {
  // New!
  @Inject lateinit var viewModelFactory: MainActivityViewModelFactory
  private val viewModel by lazy(mode = LazyThreadSafetyMode.NONE) {
    ViewModelProviders.of(this, viewModelFactory)
      .get(MainActivityViewModel::class.java)
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    AndroidInjection.inject(this)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // New!
    viewModel.counter().observe(this, Observer {
      // Assuming the existence of a TextView with the id "counterText"
      counterText.text = it.toString()
    })
    // Assuming the existence of a Button with the id "counterButton"
    counterButton.setOnClickListener {
      viewModel.onClickCounter()
    }
  }
}

```
Here's what we've changed from last time:
1. We're injecting a "view model factory", which is literally a [ViewModelProvider.Factory](https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider.Factory). This is only necessary if your `ViewModel` has a non-default constructor. In other words, it's absolutely necessary as soon as you want to do anything interesting.
2. We use our view model factory to provide our actual ViewModel, which is the thing we really care about.
3. We're using `by lazy` because we really like immutability, and it's the only way to have a `val` view model. (See the note at the bottom of this article for why I'm setting the mode.)
4. We then use our ViewModel in concert with a couple of widgets.

The eagle-eyed among you will have noticed that we're injecting a new object (`MainActivityViewModelFactory`), but I haven't shown any code for how to inject this new object. Doesn't it need a `@Provides` or `@Binds` inside a `@Module`? Not so much. Dagger supports two kinds of bindings, which I will refer to as "explicit" and "implicit." 

## Explicit bindings

```kotlin
@Module abstract class MyModule {
  @Binds abstract fun bindThing(impl: ThingImpl): IThing
  @Provides @JvmStatic fun provideThingama(bob: Bob): Thingama = Thingama(bob)
}
```

In this case, we are explicitly telling Dagger how it can create instances of `IThing`s and `Thingama`s. In the first case, we bind the `IThing` interface to its concrete implementation `ThingImpl`, and therefore we use `@Bind`. In the second case, the `Thingama` class (tragically) doesn't implement an interface, so we have to provide instances of it directly, and therefore we use `@Provides`.

But even here we see that I've cheated. Where does `ThingImpl` come from? What about `Bob`?

## Implicit bindings
```kotlin
class ThingImpl @Inject constructor()

class Bob @Inject constructor()
```
These are implicit bindings, and they simply require we annotate one of our constructors (even a default one!) with `@Inject`.

_Of course_,  we can specify non-default constructors with an arbitrary number of parameters, and still rely upon Dagger to instantiate these objects &mdash; just so long as our **D**irected **A**cyclic **G**raph of dependencies contains the information **DAG**ger needs to provide each of the required objects.

# `MainActivityViewModelFactory`

For _trivial_ `ViewModel`s, we could follow the basic sample code in the docs and just do this:

```kotlin
// `this` can be a variety of things, but in our example, it is an `Activity`
private val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
```

and, as you can see, nary a factory to be seen.

But if our view model is at all _interesting_, it will certainly require collaborators; that is, a non-default constructor. For example:

```kotlin
class MutableObject(var counter: Int = 0)

class MainActivityViewModel(
  private val mutableObject: MutableObject
) : ViewModel() {
  // We need our counter to be mutable...
  private val counterLiveData = MutableLiveData<Int>()
  // ...but we only want to expose it to observers as an immutable object
  fun counter(): LiveData<Int> = counterLiveData

  init {
    // initialize it to something, else `value` will be `null`, which is annoying
    counterLiveData.value = mutableObject.counter
  }

  // Clicking increments the counter. Nothing simpler!
  fun onClickCounter() {
    counterLiveData.value = ++mutableObject.counter
  }
}
```

but if we tried to get a reference to such a view model with the above example, it would fail! There is a _default_ `ViewModelProvider.Factory` that knows how to create `ViewModel`s with _default_ (no-arg) constructors, but it can't possibly know how to create our custom view model.

# ViewModelProvider.Factory

You will certainly have noticed the following:
```kotlin
ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)
```
This is an overload on the `ViewModelProviders.of()` method that takes a custom factory. What does one of those look like? Here's one way to do it:
```kotlin
class MutableObjectFactory @Inject constructor() {
  fun newMutableObject() = MutableObject()
}

class MainActivityViewModelFactory @Inject constructor(
  private val mutableObjectFactory: MutableObjectFactory
) : ViewModelProvider.Factory {

  @Suppress("UNCHECKED_CAST")
  override fun <T : ViewModel> create(modelClass: Class<T>): T {
    return when {
      modelClass.isAssignableFrom(MainActivityViewModel::class.java) -> {
        MainActivityViewModel(mutableObjectFactory.newMutableObject()) as T
      }
    else -> throw IllegalArgumentException(
        "${modelClass.simpleName} is an unknown type of view model"
      )
    }
  }
}
```

We have defined two new classes here. Let's talk about the view model factory, first.

## ViewModelProvider.Factory, defined

This is an interface that declares a single method, `create()`. It takes a a reference to the class it must create, and returns an instance of that class. If we strip it down, this is what we have:

```kotlin
class MyViewModelFactory : ViewModelProvider.Factory {
  @Suppress("UNCHECKED_CAST")
  override fun <T : ViewModel> create(modelClass: Class<T>): T {
    return MyViewModel() as T
  }
}
```
and this is essentially what the default factory does.

The other class, `MutableObjectFactory`, is trivial. I've declared it to showcase an important point.

# Why do we care about `ViewModel`s at all?

We care about `ViewModel`s because they
1. _Live outside_ the Activity/Fragment lifecycle
2. _Know about_ the Activity/Fragment lifecycle.

This is _amazingly useful_. Because view models live outside of the lifecycle, they don't get destroyed every time your activity gets destroyed (haha, rotation, go away). But because they also _know about_ the lifecycle, you can start observing a `LiveData` object in `Activity.onCreate()`, and you will only receive updates on that object while the the activity is in the "started" state (between `onStart` and `onStop`).

In the context of Dagger, this is a bit like having a custom `@Scope`, without having to declare or manage one. We create our objects in `Activity.onCreate()`, mutate those objects, rotate the screen, _get references to those same objects again_, and keep on going, no problem at all.

**There is a small gotcha**, though. Here's that activity code, one more time:

```kotlin
class MainActivity : AppCompatActivity() {

  // Hmmm
  @Inject lateinit var viewModelFactory: MainActivityViewModelFactory

  private val viewModel by lazy {
    ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    // Hmmmmm
    AndroidInjection.inject(this)

    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    viewModel.counter().observe(this, Observer {
      counterText.text = it.toString()
    })
    counterButton.setOnClickListener {
      viewModel.onClickCounter()
    }
  }
}
```

_Every time_ we rotate our device, the activity goes through `onDestroy`/`onCreate`. Therefore, _every time_ we rotate our device, we inject a **new** view model factory! _However_, even though the _factory_ is new, the call to `ViewModelProviders.of(this, factory).get(MyViewModel::class.java)` will return the _same_ view model! The Android Architecture Component framework maintains a separate map of class-to-view model that is independent from Dagger. So, each time you try to get a reference to a view model that already exists, it returns the extant instance.

## Heavy objects and `MutableObjectFactory`

This brings us back to `MutableObjectFactory`. If, instead of providing that factory to our view model factory, we provided an instance of `MutableObject` itself, we'd be instantiating a new `MutableObject` each time we instantiated a view model factory which, incidentally, is every time we inject a view model factory in our activity &mdash; and that's every time we rotate. If `MutableObject` is very heavy, then we'd like to avoid creating new instances that will never get used. So, we provide a factory instead. Illustrating in code:

```kotlin
// New instances of this class are created each time we inject our activity
class MainActivityViewModelFactory @Inject constructor(
  // that means new instances of this factory are created each time
  private val mutableObjectFactory: MutableObjectFactory
) : ViewModelProvider.Factory {
  @Suppress("UNCHECKED_CAST")
  override fun <T : ViewModel> create(modelClass: Class<T>): T {
    return when {
      // HOWEVER, this code will ONLY BE CALLED ONCE
      modelClass.isAssignableFrom(MainActivityViewModel::class.java) -> {
        MainActivityViewModel(mutableObjectFactory.newMutableObject()) as T
      }
      else -> throw IllegalArgumentException(
        "${modelClass.simpleName} is an unknown type of view model"
      )
    }
  }
}
```

You may be thinking (like me) "ew, gross. Creating a factory is better than creating the heavy object itself, but can I avoid even creating that factory?" Well... yes, but. You can declare and manage a custom Dagger `@Scope` to handle that. You can use static instances, somehow. You can get really clever with programming techniques. Or you can profile this code and decide for yourself if it's worth the effort. (A future post will discuss custom scopes.)

Is that it for view models? Not quite. We still have yet to discuss them in the context of fragments, and believe me, there are some interesting gotchas there. But... until next time.

# Notes
1. Synchronization mode for Kotlin's `by lazy`. We use `mode = LazyThreadSafetyMode.NONE` because the default mode is `LazyThreadSafetyMode.SYNCHRONIZED`, which uses the [double-checked locking pattern](https://en.wikipedia.org/wiki/Double-checked_locking) to ensure only one instance of this object is ever created. This adds overhead we don't want, because we want to minimize the work done on the main thread. We achieve the goal of "just one instance" but only accessing our ViewModel on the main thread; because our programming model is single-threaded, there's no chance of our `by lazy` being called in a concurrent way, and therefore no chance of accidentally creating multiple instances of our ViewModel.