4
votes

Dague / MissingBinding java.util.Map , Provider > ne peut pas être fourni sans une méthode annotée @ Provides

Voici comment j'essaye de fournir mon ViewModelFactory:

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory

Et c'est ainsi que je lie la ViewModelFactory :

di/Injector.java:9: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.

Je reçois l'erreur suivante lors de la compilation:

@Suppress("unused")
@Module
abstract class ViewModelModule  {
    @Binds
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class)
    internal abstract fun mainViewModel(viewModel: MainViewModel): ViewModel
}

De mon Activité code > J'essaye de recevoir la ViewModelFactory de cette façon:

@Suppress("UNCHECKED_CAST")
@Singleton
class ViewModelFactory @Inject constructor(
    private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)


0 commentaires

3 Réponses :


6
votes

Après avoir creusé un peu plus, j'ai trouvé le problème. Cela n'a aucun rapport avec le code que j'utilise. Cela concerne Kotlin 1.3.30 .

Voici plus d'informations à ce sujet.

La mise à niveau vers Kotlin 1.3.21 a résolu le problème.


2 commentaires

Selon le problème GitHub , l'utilisateur bleeding182 a suggéré a solution de contournement pour refactoriser à la place ViewModelKey en Java. Ça marche pour moi.


Bonjour, veuillez vérifier la solution ci-dessous.



6
votes

J'ai récemment rencontré le même problème. Version Kotlin: 1.3.40 Dague: 2.23.2 J'ai essayé de suivre les solutions mentionnées dans cet article et ici

mais aucune ne semblait fonctionner . Le processeur d'annotation de Dagger ne fonctionne pas bien avec KAPT et pour la même raison, les builds échouent. Ceci est également mis à jour sur le problème de Kotlin.

Pour moi, la conversion de ViewModelKey et ViewModelFactory en java a fonctionné. Pour Dagger, le problème de suivi peut être trouvé ici .

Mettre à jour L'ajout de @JvmSuppressWildcards a résolu le problème. Le code ressemble à ceci:

private val providers: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>


2 commentaires

Tout mon code était dans kotlin.Convertir à la fois ViewModelKey et ViewModelFactory en java a fonctionné. Merci. L'ajout de @JvmSuppressWildcards n'a pas fonctionné


C'est incroyable mon frère.



-2
votes

Tout d'abord ViewModelFactory ne doit pas être un Singleton. Quoi qu'il en soit, pour résoudre ce problème, vous devriez avoir:

  • une ViewModelFactory

    classe ViewModelFactory @Inject constructeur ( créateurs de val privés: Map , @JvmSuppressWildcards Provider > ): ViewModelProvider.Factory { remplacement amusant create (modelClass: Class ): T { val creator = creators [modelClass]?: creators.entries.firstOrNull { modelClass.isAssignableFrom (it.key) } ?. value?: throw IllegalArgumentException ("classe de modèle inconnue $ modelClass") essayez { @Suppress ("UNCHECKED_CAST") renvoie creator.get () comme T } catch (e: Exception) { lancer RuntimeException (e) } } }

  • liez cette fabrique dans votre classe de module

    @Binds abstrait amusant bindViewModelFactory (usine: ViewModelFactory): ViewModelProvider.Factory

  • ont une ViewModelKey

    @Retention (AnnotationRetention.RUNTIME) @Target (AnnotationTarget.FUNCTION) @Carte clé classe d'annotation ViewModelKey (valeur val: KClass )

  • liez votre viewModel dans le module souhaité

    @Binds @IntoMap @ViewModelKey (MyViewModel :: classe) abstrait amusant bindCustomViewModel (viewModel: MyViewModel): ViewModel

  • puis implémentez et utilisez votre viewModel

    @Inject lateinit var viewModelFactory: ViewModelFactory

    valeur privée viewModel: MyViewModel by viewModels {viewModelFactory}

Cette solution est testée avec Kotlin 1.3.72 et la dernière version de Dagger2 . Veuillez également vérifier sur https://github.com/android/architecture- composants-échantillons / tree / master / GithubBrowserSample

J'espère que cela vous aidera.


1 commentaires

Mise à jour: maintenant Hilt supprime ce problème. Veuillez utiliser @ViewModelInject. Veuillez vous référer à developer.android.com/training/dependency-injection/…