Dagger / MissingBinding java.util.Map <java.lang.class <?如果没有@Provides注释的方法,则不能提供extend =“” viewmodel =“”>,Provider <viewmodel >>

时间:2019-04-13 20:57:29

标签: android kotlin dependencies dagger-2 dagger

这就是我要提供我的ViewModelFactory的方式:

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

这就是我绑定ViewModelFactory的方式:

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

在构建过程中收到以下错误:

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.

我正尝试通过以下方式从我的Activity接收ViewModelFactory

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory

4 个答案:

答案 0 :(得分:6)

深入研究之后,我发现了问题。 它与我使用的代码完全无关。它以Kotlin 1.3.30为例。

Here有关此信息的更多信息。

降级为Kotlin 1.3.21解决了该问题。

答案 1 :(得分:0)

我最近遇到了同样的问题。 版本 科特琳:1.3.40 Dagger:2.23.2 我尝试遵循本文和here

中提到的解决方案

但似乎没有一个起作用。 Dagger的注释处理器不能与KAPT配合使用,并且由于相同的原因,构建失败。 Kotlin issue上也对此进行了更新。

对我来说,将ViewModelKeyViewModelFactory都转换为Java是可行的。 对于Dagger,可以在here中找到跟踪问题。

更新 添加@JvmSuppressWildcards解决了该问题。代码如下:

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

答案 2 :(得分:0)

 No need to Downgrade the Kotlin version. As the day of Post my Kotlin version
 is : '1.3.40'

 Use dagger dependency in build.gradle

 apply plugin: 'kotlin-kapt'

 //Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
kapt 'com.google.dagger:dagger-compiler:2.22.1'

implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.22'


And for Java use the following dagger dependency

 //Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1'

implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.22'

答案 3 :(得分:-2)

首先ViewModelFactory不应该是Singleton。无论如何要解决此问题,您都应该具有:

  • 一个ViewModelFactory

    class ViewModelFactory @Inject constructor( private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>> ) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val creator = creators[modelClass] ?: creators.entries.firstOrNull { modelClass.isAssignableFrom(it.key) }?.value ?: throw IllegalArgumentException("unknown model class $modelClass") try { @Suppress("UNCHECKED_CAST") return creator.get() as T } catch (e: Exception) { throw RuntimeException(e) } } }

  • 将此工厂绑定到您的模块类中

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

  • 具有ViewModelKey

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

  • 将viewModel绑定到所需的模块中

    @Binds @IntoMap @ViewModelKey(MyViewModel::class) abstract fun bindCustomViewModel(viewModel: MyViewModel): ViewModel

  • 然后实现并使用您的viewModel

    @Inject lateinit var viewModelFactory: ViewModelFactory

    private val viewModel: MyViewModel by viewModels { viewModelFactory }

此解决方案已通过Kotlin 1.3.72和最新版本的Dagger2进行了测试。 另外,请检查https://github.com/android/architecture-components-samples/tree/master/GithubBrowserSample

希望这会对您有所帮助。