2017-09-26 196 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