【问题标题】:Kotlin + Dagger - inject Map for ViewModel factoryKotlin + Dagger - 为 ViewModel 工厂注入 Map
【发布时间】:2018-02-13 01:00:52
【问题描述】:

我正在使用带有 Dagger2 的新架构组件,我想使用工厂类注入我的 ViewModel。 Factory 类本身是可注入的。当在 Java 中定义 Factory 类时,这一切都很好,但是当我将其转换为 Kotlin 时,Dagger2 不知道如何为构造函数生成 Map,而在 Java 中它知道如何生成。我认为不同之处在于,转换后,Factory 类使用 kotlin 包中的 Map,而不是 java.util.Map 包中的 Map。如何让 Dagger2 为 Factory 构造函数生成地图?

这是工厂类

@ActivityScope
class MainActivityViewModelFactory @Inject
constructor(private val creators: Map<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {

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

    }
}

这是错误

Error:java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.

我尝试创建一个模块来提供地图,但这没有帮助。

@ActivityScope
@Module
class MapModule {
    @Provides
    fun provideMap(): Map<Class<out ViewModel>, Provider<ViewModel>> = mutableMapOf()
}

【问题讨论】:

    标签: android kotlin dagger-2


    【解决方案1】:

    我稍微修改了你的ViewModelFactory 代码:

    @ActivityScope
    class MainActivityViewModelFactory @Inject
    constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
    
        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)
            }
    
        }
    }
    

    你可以试试这个吗? 我添加了@JvmSuppressWildcards 注释。

    有关更多信息,您可以查看: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-suppress-wildcards/index.html

    编辑: 你可以从我的 repo 中找到一个现场演示:https://github.com/savepopulation/dc-tracker

    【讨论】:

    • 我猜你可能会在需要 Java Map 的地方使用 MutableMap。因为 Kotlin 的不变性
    • 如果不能使用构造函数注入,你会怎么做?看到这个帖子:stackoverflow.com/questions/56739361/…
    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多