question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ViewModel init call

See original GitHub issue

Hi, I get your sample code for ViewModel

class BackpackViewModel : ViewModel() {
    val backpack: Backpack by inject()
}

and add an initialization block like here

class BackpackViewModel : ViewModel() {
    val backpack: Backpack by inject()
    init {
        backpack.doSomething()
    }
}

But I got this exception

java.lang.IllegalStateException: The dependency has not be injected yet.

If i call backpack.doSomething() after init call everything is working.

How I fix it?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
mrgariccommented, Jul 27, 2020

I think an example will be enough. thx.

1reaction
dlemurescommented, Jul 19, 2020

@afaucogney is right (thx for the answer!), creation happens before injection. The process is divided into 2 steps:

  1. When you use installViewModelBinding on your scope, we create the viewmodel using the right APIs under the hood.
  2. When you start the injection, for example calling KTP...inject() inside your activity, it’s when we inject the dependencies of the viewmodel.

The issue is that you are trying to access to those dependencies on the first step, when they are not ready yet. This is similar to when you wanna access injected fields inside a constructor. If you are curious, I could explain more about the reasons why we designed it that way.

Nevertheless, there is a way to solve it: using a ViewModel Factory to create the viewmodel using Toothpick.

val scope = KTP.openScopes(xxx)
scope.installViewModelBinding<MyViewModel>(activity, InjectedViewModelProvider(scope))
...

// This provider can be reused for any ViewModel
class InjectedViewModelProvider(private val scope: Scope) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return scope.getInstance(modelClass)
    }
}

class BackpackViewModel(private val backpack: Backpack) : ViewModel() {
    init {
        backpack.doSomething()
    }
}

By doing so, you can use constructor and field injection within your viewmodel.

Same, if you are curious, I can provide more info about why we don’t provide that functionality out-of-the-box.

Read more comments on GitHub >

github_iconTop Results From Across the Web

android - init is not called when injecting viewModel using Hilt
But there is one case that when I call a function from viewModel inside activity first init triggers, and then that function is...
Read more >
How I can call a Init() function from my ViewModel?
Hi Markus, include call Init method in ctor of ViewModel. Your code ist a mixture of CodeBehind and MVVM. <Grid DataContext="{StaticResource vm} ...
Read more >
ViewModel initialization - RainbowCake
This is best done by fetching the state in the ViewModel 's initializer block ( init ). This approach is useful if fetching...
Read more >
Jetpack ViewModel initialization - Rock and Null
ViewModels in Android Jetpack is an awesome approach for decoupling business logic from Activities/Fragments. And is extremely easy to get ...
Read more >
ViewModel overview - Android Developers
ViewModel lets you manage your UI's data in a lifecycle-aware fashion.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found