Recommended Ways To Create ViewModel or AndroidViewModel
Tags: android, kotlin, beginners
Published: 2021-10-08 23:01:37

**Kotlin examples to show different ViewModel and AndroidViewModel implementations**

There are few ways to create `ViewModel` and `AndroidViewModel`. This article shows you the Kotlin examples of creating them.

This is an example of `ViewModel` or `AndroidViewModel` class that you may have.

```kotlin
class MyViewModel: ViewModel() {
}
class MyAndroidViewModel (app: Application)
    : AndroidViewModel(app) {
}
```

*The code examples here are used in fragment class. So it may not work in the activity class. Small modifications are required if you copy and paste them into your activity class.* 

*If you're not familiar Kotlin, you can go through some quick examples [here](https://vtsen.hashnode.dev/best-way-to-learn-kotlin-for-experienced-programmers)  first to understand some important concepts such as "Delegation".*


## Manual Creation - Don't do this!
```kotlin
private val viewModel = MyViewModel()
private val androidViewModel = 
    MyAndroidViewModel(requireActivity().application)
```

This works only if you don't rotate your phone. When you rotate your phone, an activity or fragment is destroyed and recreated. A new instance of `ViewModel` or `AndroidViewModel` is created again. So all the data before the screen rotation is lost. This defeats the purpose of `ViewModel` architecture. You want `ViewModel` to survive through activity or fragment destruction.

*I made this mistake because I did not understand the reason of using`ViewModelProvider` to create `ViewModel`*

## lateinit var with ViewModelProvider
```kotlin
private lateinit var viewModel: MyViewModel
private lateinit var androidViewModel: MyAndroidViewModel
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {

    viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
    androidViewModel =          
        ViewModelProvider(this).get(MyAndroidViewModel::class.java)
}
```

Using `ViewModelProvider` is the right way to create `ViewModel`. When the activity or fragment is created, `ViewModelProvider` is smart enough to figure out to reuse the first created `ViewModel` instance. 

If `ViewModel` doesn't change (which is likely true), using `val` Kotlin variable is a better option here.

## by lazy with ViewModelProvider
To use `val` variable, you use [by lazy](https://vtsen.hashnode.dev/complete-c-to-kotlin-syntax-comparisons#heading-by-lazy-delegated-properties) property initialization. The delegated block gets executed when the variable is first accessed.

```kotlin
private val viewModel: MyViewModel by lazy {
    ViewModelProvider(this).get(MyViewModel::class.java)
}

private val androidViewModel: MyAndroidViewModel by lazy {
    ViewModelProvider(this).get(MyAndroidViewModel::class.java)
}
```

The code looks a lot cleaner than `lateinit var` solution. However, another elegant way is to use `by viewModels` or `by activityViewModels`.
 
## by viewModels / activityViewModels
To use this Property Delegation, the following dependency needs to be added to the build.gradle (module-level). The version is just an example, you can use later or latest version.

```
implementation 'androidx.fragment:fragment-ktx:1.3.6'
```

The following code is awesome! It essentially does the same thing as `by lazy` without the need to specify the `ViewModelProvider`. It automatically figures out that for you.

```kotlin
private val viewModel: MyViewModel by viewModels()
private val androidViewModel: MyAndroidViewModel by viewModels()
```

If you want to share your `ViewModel` across different fragments within the same activity. You can use `by activityViewModels`.

```kotlin
private val viewModel: MyViewModel by activityViewModels()
private val androidViewModel: MyAndroidViewModel 
    by activityViewModels()
```

## by viewModels (Custom Constructor Parameter)
It is very common to pass additional objects to the `ViewModel` constructor. The following example is passing `Repository` object into the `MyViewModel` and `MyAndroidViewModel`.

```kotlin
class MyViewModel(private val repository: Repository)
    : ViewModel() {
}

class MyAndroidViewModel(app: Application, repository: Repository)
    : AndroidViewModel(app) {
}
```

Having a custom constructor parameter for `ViewModel` is a bit complicated. You need to have a custom `ViewModel` factory to create your `ViewModel`.

To create your custom `ViewModel` factory, you can inherit from `ViewModelProvider.NewInstanceFactory`.

```kotlin
class MyViewModelFactory(private val repository: Repository)
    : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
```

For custom `AndroidViewModel` factory, you can inherit from `ViewModelProvider.AndroidViewModelFactory`

```kotlin
class MyAndroidViewModelFactory(
    private val app: Application,
    private val repository: Repository)
    : ViewModelProvider.AndroidViewModelFactory(app) {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(
                MyAndroidViewModel::class.java)) {
                    
            return MyAndroidViewModel(app, repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
```

> **[Updated - Oct 30, 2021]:** In fact, we can just implement the `ViewModelProvider.Factory` interface for both `MyViewModelFactory` and `MyAndroidViewModelFactory`. Examples can be found here.

- [Implement ViewModelProvider.Factory Interface for Custom ViewModel / AndroidViewModel Factory Creation](https://vtsen.hashnode.dev/implement-viewmodelproviderfactory-interface-for-custom-viewmodel-androidviewmodel-factory-creation).

To create `ViewModel` with your custom constructor parameter, you use `by viewModels` delegate property. 

```kotlin
private val viewModel: MyViewModel by viewModels {
    
    MyViewModelFactory(Repository())
}

private val androidViewModel: MyAndroidViewModel by viewModels {

    MyAndroidViewModelFactory(
        requireActivity().application,
        Repository())
}
```

You can replace `by viewModels` with `by ActivityViewModels` if you want your `ViewModel` to survive in different fragments within the same activity.

```kotlin
private val viewModel: MyAndroidViewModel by activityViewModels {

    MyViewModelFactory(Repository())
}

private val androidViewModel: MyAndroidViewModel 
    by activityViewModels {

        MyAndroidViewModelFactory(
            requireActivity().application,
            Repository())
    }
```

> **[Updated -  Nov 7, 2021]:** you can also use `by lazy` and `ViewModelProvider()` instead of `by viewModels` and it should still work. It can't be used to replace `by activityViewModels` because the created `ViewModel`won't be shared across different fragments. So this is just for your reference and knowledge.


```kotlin
private val viewModel: MyViewModel by lazy {
    val factory = MyViewModelFactory(Repository())

    ViewModelProvider(this, factory).get(MyAndroidViewModel::class.java)
}
```

```kotlin
private val viewModel: MyAndroidViewModel by lazy {
    val factory = MyAndroidViewModelFactory(
        requireActivity().application, 
        Repository())

    ViewModelProvider(this, factory).get(MyAndroidViewModel::class.java)
}
```

## My Common Practices
The fun thing about programming is there are many ways to do the same thing. Understand the differences, make you a better programmer.

I use the last method - by viewModels (Custom Constructor Parameter) by default because  I usually have custom constructor parameters in my ViewModel. 

Also, I usually use `by activityViewModels` instead of `by viewModels` which allows me to share data across different fragments. It saves my time to figure out how to pass data to different fragments. For example, using `Bundle`to share data between fragments.

I also use `AndroidViewModel` by default instead of `ViewModel` because I usually need to access string resources and system services from the `Application` context. There are drawbacks being discussed over the internet, but I do not fully understand this part yet. For now,  `AndroidViewModel` is good for me.

These are my common practices. I'm not sure other Android developers agree with me. Let me know your thoughts.

> **[Updated - July 15, 2022]:** I managed to try `hilt` to inject the dependencies ito view model. Here is the example:
- [Convert View Model to Use Hilt Dependency Injection](https://vtsen.hashnode.dev/convert-view-model-to-use-hilt-dependency-injection)

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/recommended-ways-to-create-viewmodel-or-androidviewmodel)*.