Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject app: Context in ViewModel with Hilt?

Hello, I'm trying to inject view model using Hilt, but I get the following error:

 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.wordssample, PID: 25250
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.wordssample/com.example.wordssample.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.wordssample.MainViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
  
 Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.wordssample.MainViewModel
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
    at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:74)
    at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 

This is my MainActivity:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
   
    private val viewModel  by viewModels<MainViewModel>()


    override fun onCreate(savedInstanceState: Bundle?) {
      ....

And this is the ViewModel class I'm trying to inject

class MainViewModel @ViewModelInject constructor(
    @ApplicationContext application: Context,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val repositorio = WordRepositorio(application)

    val allWords = repositorio.mAllWords
...

I appreciate the help! Thanks

like image 778
Tarsila Costalonga Avatar asked Jul 28 '20 23:07

Tarsila Costalonga


People also ask

How do you inject a ViewModel with hilt?

To use @HiltViewModel , you'll need to add these 2 libraries on top of the Dagger Hilt Libraries added as shared in the article above. In your ViewModel, just add @HiltViewModel before the class and the usual @Inject to the constructor. Here we auto have the savedStateHandler injected too.

What is HiltViewModel?

Annotation Type HiltViewModelIdentifies a ViewModel for construction injection. The ViewModel annotated with HiltViewModel will be available for creation by the dagger. hilt. android. lifecycle.

What is AndroidViewModel?

AndroidViewModel. Application context aware ViewModel . ViewModel is a class that is responsible for preparing and managing the data for an Activity or a Fragment . It also handles the communication of the Activity / Fragment with the rest of the application (e.g. calling the business logic classes).


2 Answers

Yes, there was nothing wrong with the code. The problem was in some libraries, apparently I was missing something.

I solved it by adding:

implementation 'com.google.dagger:hilt-android:2.28-alpha'

implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'

kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'

kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'

implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'

like image 184
Tarsila Costalonga Avatar answered Oct 19 '22 01:10

Tarsila Costalonga


BaseViewModel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
open class BaseViewModel @Inject constructor(application: Application) : AndroidViewModel(application) {
  protected val context
    get() = getApplication<Application>()
}

HomeViewModel

@HiltViewModel
class HomeViewModel @Inject constructor(
  application: Application,
  private val userRepository: UserRepository
) : BaseViewModel(application) {
  val text1 = MutableLiveData(context.getString(R.string.string_1))

  fun update(){
    text1.value = context.getString(R.string.string_2)
  }
}

HomeFragment

@AndroidEntryPoint
class HomeFragment : Fragment(R.layout.home_fragment) {
  private val binding: HomeFragmentBinding by dataBinding()
  private val viewModel: HomeViewModel by viewModels()

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    binding.vm = viewModel
  }
like image 26
Changhoon Avatar answered Oct 19 '22 02:10

Changhoon