2017-09-26 16 views
1

J'essaie d'utiliser poignard 2 sur mon application Android pour injecter le nouveau ViewModel de la bibliothèque android arch.Kotlin poignard 2 Android ViewModel erreur d'injection

D'après ce que je vois sur cet échantillon https://github.com/googlesamples/android-architecture-components/tree/e33782ba54ebe87f7e21e03542230695bc893818/GithubBrowserSample je dois utiliser:

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

@Module 
abstract class ViewModelModule { 
    @Binds 
    @IntoMap 
    @ViewModelKey(LoginViewModel::class) 
    internal abstract fun bindLoginViewModel(viewModel: LoginViewModel): LoginViewModel 

    @Binds 
    @IntoMap 
    @ViewModelKey(MainMenuViewModel::class) 
    internal abstract fun bindSearchViewModel(viewModel: MainMenuViewModel): MainMenuViewModel 

    @Binds 
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory 
} 

@ApplicationScope 
@Component(modules = arrayOf(ApplicationModule::class, NetworkModule::class, ViewModelModule::class)) 
interface ApplicationComponent { 
    fun plusActivityComponent(activityModule: ActivityModule): ActivityComponent 
    fun inject(application: LISAApplication) 

} 

Et mon usine est:

@ApplicationScope 
class ViewModelFactory @Inject constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory { 

    @Suppress("UNCHECKED_CAST") 
    override fun <T : ViewModel> create(modelClass: Class<T>): T { 
     var creator: Provider<out ViewModel>? = creators[modelClass] 
     if (creator == null) { 
      for ((key, value) in creators) { 
       if (modelClass.isAssignableFrom(key)) { 
        creator = value 
        break 
       } 
      } 
     } 
     if (creator == null) { 
      throw IllegalArgumentException("unknown model class " + modelClass) 
     } 
     try { 
      return creator.get() as T 
     } catch (e: Exception) { 
      throw RuntimeException(e) 
     } 

    } 
} 

Mais le projet ne compile pas :(Je cette erreur (Carte < ...> ne peut pas être fourni sans @ méthode Procure-annotée.):

Using Kotlin incremental compilation 
:mobile:transformDataBindingWithDataBindingMergeArtifactsForDebug UP-TO-DATE 
:mobile:kaptDebugKotlin 
e: /Users/jaumard/LISAProjects/LISA/mobile/build/tmp/kapt3/stubs/debug/com/mylisabox/lisa/dagger/components/ApplicationComponent.java:6: error: [com.mylisabox.lisa.dagger.components.ActivityComponent.inject(com.mylisabox.lisa.common.BaseActivity)] java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method. 
e: 

e: public abstract interface ApplicationComponent { 
e:    ^
e:  java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at 
e:   com.mylisabox.lisa.dagger.ViewModelFactory.<init>(creators) 
e:  com.mylisabox.lisa.dagger.ViewModelFactory is injected at 
e:   com.mylisabox.lisa.common.BaseActivity.factory 
e:  com.mylisabox.lisa.common.BaseActivity is injected at 
e:   com.mylisabox.lisa.dagger.components.ActivityComponent.inject(activity) 
e: /Users/jaumard/LISAProjects/LISA/mobile/build/tmp/kapt3/stubs/debug/com/mylisabox/lisa/dagger/components/ActivityComponent.java:4: error: com.mylisabox.lisa.dagger.components.ActivityComponent scoped with @com.mylisabox.network.dagger.annotations.ActivityScope may not reference bindings with different scopes: 
e: 

Une idée sur comment résoudre ce problème?

+0

eu un problème similaire en utilisant '@ annotation Binds' avec Kotlin - je devais changer pour retourner une mise en œuvre concrète avec' @ Provides' plutôt qu'une méthode abstraite. Serait bien si quelqu'un peut offrir une solution. –

+0

Bonjour Mark, donc vous voulez dire que vous supprimez toutes les méthodes abstraites et que vous préférez @Provides? Sorcière signifie que la carte doit être construite manuellement? – jaumard

+0

Trouvez la réponse pour moi, vérifiez-la, j'espère que cela fonctionnera pour vous aussi – jaumard

Répondre

2

Donc, j'ai trouvé le problème, le problème était sous mon ViewModelModule Je dois retourner ViewModel de mes méthodes abstraites pas directement le type que je veux. Il deviendra alors comme ceci:

@Module 
abstract class ViewModelModule { 
    @Binds 
    @IntoMap 
    @ViewModelKey(LoginViewModel::class) 
    internal abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel 

    @Binds 
    @IntoMap 
    @ViewModelKey(MainMenuViewModel::class) 
    internal abstract fun bindSearchViewModel(viewModel: MainMenuViewModel): ViewModel 

    @Binds 
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory 
} 
+1

Je l'avais fait mais ça a quand même échoué. J'ai dû annoter 'Provider >' avec l'annotation '@ JvmSuppressWildcards' pour que cela fonctionne. 'classe ViewModelFactory @Inject constructeur (private val créateurs: Map , @JvmSuppressWildcards Fournisseur >): ViewModelProvider.Factory {' –

+0

Vous avez raison, @JvmSuppressWildcards est obligatoire, je ne l'ai pas mis dans mon répondre car il était déjà présent sur mon code d'usine de ma question – jaumard