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 上进行了更新。

对我来说,将 ViewModelKeyViewModelFactory 都转换为 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

更新到 Kotlin 1.3.30 会破坏 Dagger 2.21 的构建

如何使用 Hilt 在存储库中注入应用程序上下文?

javs switch 语句

JAV所有开发公共代码