Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo
Posted
技术标签:
【中文标题】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 【发布时间】:2019-09-04 07:00:39 【问题描述】:这就是我试图提供我的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
【问题讨论】:
【参考方案1】:我最近遇到了同样的问题。 版本 科特林:1.3.40 匕首:2.23.2 我尝试按照本文中提到的解决方案和here
但似乎没有一个工作。 Dagger 的注释处理器不能很好地与 KAPT 配合使用,出于同样的原因,构建失败了。这也在 Kotlin issue 上进行了更新。
对我来说,将 ViewModelKey
和 ViewModelFactory
都转换为 java 是可行的。
对于 Dagger,可以在 here 找到跟踪问题。
更新
添加@JvmSuppressWildcards
解决了这个问题。代码如下所示:
private val providers: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
【讨论】:
我所有的代码都在 kotlin 中。将 ViewModelKey 和 ViewModelFactory 都转换为 java 工作。谢谢。添加@JvmSuppressWildcards 无效 这太棒了我的兄弟。 你这个男人。 @JvmSuppressWildcards 获胜。【参考方案2】:在深入挖掘之后,我发现了问题所在。
它与我正在使用的代码完全无关。这是Kotlin 1.3.30
。
Here有关它的更多信息。
降级到Kotlin 1.3.21
解决了这个问题。
【讨论】:
根据the GitHub issue,用户bleeding182 建议a workaround 改为将ViewModelKey
重构为Java。它对我有用。
您好,请查看以下解决方案。【参考方案3】:
首先 ViewModelFactory 不应该是单例。无论如何要解决这个问题,你应该有:
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
希望这会对你有所帮助。
【讨论】:
更新:现在 Hilt 抑制了这个问题。请使用@ViewModelInject。请参考developer.android.com/training/dependency-injection/…以上是关于Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo的主要内容,如果未能解决你的问题,请参考以下文章
错误:[Dagger/MissingBinding] Map<Class<?扩展 ViewModel>, Provider<ViewModel>> 不能在没有 @P
Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo