2017-09-26 103 views
1

我试图在我的Android应用程序上使用匕首2从arch android库注入新的ViewModel。Kotlin匕首2 Android ViewModel注入错误

从我看到这个样本https://github.com/googlesamples/android-architecture-components/tree/e33782ba54ebe87f7e21e03542230695bc893818/GithubBrowserSample我需要使用这样的:

@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) 

} 

而且我厂是:

@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) 
     } 

    } 
} 

但该项目不编译:(我有这个错误(地图< ...>不能提供@提供注释的方法。):

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: 

关于如何解决这个问题的任何想法?

+0

使用'与科特林@ Binds'注释也有类似的问题 - 我不得不改变返回的具体实现与'@ Provides',而不是一个抽象的方法。如果有人能提供解决方案,那将会很好。 –

+0

你好马克,所以你的意思是你删除所有的抽象方法,而不是@Provides?女巫意味着地图必须手动构建? – jaumard

+0

找到我的答案,检查它,希望它也能为你工作 – jaumard

回答

2

因此,我确定发现问题,问题出在我的ViewModelModule下,我需要从我的抽象方法中返回ViewModel,而不是直接返回我想要的类型。它会变成这个样子,那么:

@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

我已经这样做了,但仍然失败。我不得不使用'@ JvmSuppressWildcards'注释'Provider >'注释它的工作。 'class ViewModelFactory @Inject constructor(private val creators:Map ,@JvmSuppressWildcards Provider >):ViewModelProvider.Factory {' –

+0

'你是对的,@JvmSuppressWildcards是强制性的,我没有把它放在我的回答是因为它已经出现在我的问题的工厂代码中 – jaumard