Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewModel>> 无法在没有 @Provides 注释的方法的情况下提供
Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewModel>> cannot be provided without an @Provides-annotated method
这就是我尝试提供 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
在进一步挖掘之后,我发现了这个问题。
它与我正在使用的代码完全无关。它考虑 Kotlin 1.3.30
.
Here 一些关于它的更多信息。
降级到 Kotlin 1.3.21
解决了问题。
我最近遇到了同样的问题。
版本
科特林:1.3.40
匕首:2.23.2
我尝试按照 post 和 here
中提到的解决方案
但 none 似乎有效。 Dagger 的注释处理器不能很好地与 KAPT 配合使用,出于同样的原因,构建失败了。这也在 Kotlin issue 上更新。
对我来说,将 ViewModelKey
和 ViewModelFactory
都转换为 java 是可行的。
对于 Dagger,可以找到跟踪问题 here.
更新
添加 @JvmSuppressWildcards
解决了这个问题。代码如下所示:
private val providers: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
首先,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)
}
}
}
在你的模块中绑定这个工厂class
@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
希望对您有所帮助。
这就是我尝试提供 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
在进一步挖掘之后,我发现了这个问题。
它与我正在使用的代码完全无关。它考虑 Kotlin 1.3.30
.
Here 一些关于它的更多信息。
降级到 Kotlin 1.3.21
解决了问题。
我最近遇到了同样的问题。 版本 科特林:1.3.40 匕首:2.23.2 我尝试按照 post 和 here
中提到的解决方案但 none 似乎有效。 Dagger 的注释处理器不能很好地与 KAPT 配合使用,出于同样的原因,构建失败了。这也在 Kotlin issue 上更新。
对我来说,将 ViewModelKey
和 ViewModelFactory
都转换为 java 是可行的。
对于 Dagger,可以找到跟踪问题 here.
更新
添加 @JvmSuppressWildcards
解决了这个问题。代码如下所示:
private val providers: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
首先,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) } } }
在你的模块中绑定这个工厂class
@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
希望对您有所帮助。