web-dev-qa-db-fra.com

Dague-Hilt: @ViewModelInject n'injecte pas MyViewModel et Crash?

En explorant le point de vue de Dagger-Hilt, je suis l'exemple dans https://developer.androïd.com/training/dependency-Injection/hilt-jetpack#viewModels

J'essaie d'injecter le point de vue dans mon activité comme suit

import Android.app.Application
import androidx.appcompat.app.AppCompatActivity
import Android.os.Bundle
import androidx.activity.viewModels
import androidx.hilt.Assisted
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner
import dagger.hilt.Android.AndroidEntryPoint
import dagger.hilt.Android.HiltAndroidApp
import kotlinx.Android.synthetic.main.activity_main.*
import javax.inject.Inject
import javax.inject.Singleton

@HiltAndroidApp
class MainApplication: Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    private val textDataObserver =
        Observer<String> { data -> text_view.text = data }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel.showTextDataNotifier.observe(this, textDataObserver)
        btn_fetch.setOnClickListener { viewModel.fetchValue() }
    }
}

class MyViewModel @ViewModelInject constructor(
    @Assisted val savedStateHandle: SavedStateHandle,
    val repository: Repository
) :
    ViewModel(), LifecycleObserver {

    private val showTextLiveData
            = savedStateHandle.getLiveData<String>("DefaultKey")

    val showTextDataNotifier: LiveData<String>
        get() = showTextLiveData

    fun fetchValue() {
        showTextLiveData.value = repository.getMessage()
    }
}


@Singleton
class Repository @Inject constructor() {
    fun getMessage() = "From Repository"
}

Il se plaint

     Caused by: Java.lang.RuntimeException: Cannot create an instance of class com.elyeproj.simplehilt.MyViewModel
        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:69)

J'essaie de créer manuellement la viewModel à l'aide de l'usine de modèle d'affichage (approche non injection), cela fonctionne bien.

import Android.app.Application
import androidx.appcompat.app.AppCompatActivity
import Android.os.Bundle
import androidx.activity.viewModels
import androidx.hilt.Assisted
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner
import dagger.hilt.Android.AndroidEntryPoint
import dagger.hilt.Android.HiltAndroidApp
import kotlinx.Android.synthetic.main.activity_main.*
import javax.inject.Inject
import javax.inject.Singleton

@HiltAndroidApp
class MainApplication: Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels{
        MyViewModelFactory(this, Repository(), intent.extras)
    }

    private val textDataObserver =
        Observer<String> { data -> text_view.text = data }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel.showTextDataNotifier.observe(this, textDataObserver)
        btn_fetch.setOnClickListener { viewModel.fetchValue() }
    }
}

class MyViewModelFactory(
    owner: SavedStateRegistryOwner,
    private val repository: Repository,
    defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
    override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle
    ): T {
        return MyViewModel(
            handle,
            repository
        ) as T
    }
}

class MyViewModel @ViewModelInject constructor(
    @Assisted val savedStateHandle: SavedStateHandle,
    val repository: Repository
) :
    ViewModel(), LifecycleObserver {

    private val showTextLiveData
            = savedStateHandle.getLiveData<String>("DefaultKey")

    val showTextDataNotifier: LiveData<String>
        get() = showTextLiveData

    fun fetchValue() {
        showTextLiveData.value = repository.getMessage()
    }
}

@Singleton
class Repository @Inject constructor() {
    fun getMessage() = "From Repository"
}

Ai-je fait quelque chose de mal dans l'utilisation de @ViewModelInject?

9
Elye

Pour moi, toutes les dépendances ont été parfaitement placées mais ont manqué sur hériter de la classe ViewModel (Androidx.lifecycle.ViewModel)

ViewModel ()

class MainViewModel @ViewModelInject constructor(): ViewModel() 
0
Manti_Core

J'aimerais ajouter que si vous êtes sur un projet multi-module, vous devez avoir kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01' sur le :app Module également pour que cela fonctionne.

0
Jim

Essayez de rechercher les fichiers générés par votre vue Java comme ci-dessous via Rechercher sur Chemin (FR ou Ctrl + Maj + f).
[.____] enter image description here
[.____] S'il n'y a pas de généré automatique Java fichiers. Cela signifie que vous avez oublié d'ajouter cette dépendance au fichier de grades de votre module qui génère nécessaire Java Fichiers pour chaque @ ViewModelInject Annotation.

kapt "androidx.hilt:hilt-compiler:$version"

0
Yekta Sarıoğlu