ViewModel中的Kotliin匕首字段注入引发Dagger / Binding异常

时间:2019-07-19 21:48:14

标签: android kotlin dagger-2

为了在视图模型中进行DI,我遵循了this tutorial。但是我目前陷入困境。

我为我的viewmodel创建了一个ViewModelFactory,如下所示:

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

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return creators[modelClass]?.get() as T
    }
}

随后是ViewModel:

class HomeViewModel @Inject constructor(private val songsRepository: SongsRepository): ViewModel()

对于DI,我创建了两个组件。一个是我的主要应用程序组件,另一个是依赖于主要应用程序的组件。

@Singleton
@Component(modules = [AppModule::class])
public interface AppComponent {
    fun songRepository(): SongsRepository
    fun libraryManager(): LibraryManager
    fun inject(mainActivity: MainActivity)
}


@Module
public class AppModule(val application: Application){

    @Provides @Singleton
    fun providesApplication(): Application{
        return application
    }

    @Provides @Singleton
    fun providesLibraryManager(): LibraryManager {
        return LibraryManager(application)
    }

    @Provides @Singleton
    fun providesSongRepository(libraryManager: LibraryManager): SongsRepository {
        return SongsRepository(libraryManager)
    }
}

我的ViewModelModule如下:

@Module
public class ViewModelModule {

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

    @AppScope
    @Provides
    fun providesHomeViewModelFactory(providerMap: Map<Class<out ViewModel>, Provider<ViewModel>>): HomeViewModelFactory {
        return HomeViewModelFactory(providerMap)
    }

    @AppScope
    @IntoMap
    @Provides
    @ViewModelKey(HomeViewModel::class)
    fun providesHomeViewModel(songsRepository: SongsRepository): HomeViewModel{
        return HomeViewModel(songsRepository)
    }
}

@AppScope
@Component(modules = [ViewModelModule::class], dependencies = [AppComponent::class])
public interface ViewModelComponent {
    fun homeViewModelFactory(): HomeViewModelFactory
    fun homeViewModel(): HomeViewModel
    fun inject(homeFragment: HomeFragment)
}

我得到的错误是:

  错误:[Dagger / MissingBinding] java.util.Map ,?延伸   javax.inject.Provider>不能为   无需使用@Provides注释的方法即可提供。

我真的不知道为什么会这样,因为我所有的类都有@Inject构造函数。匕首的文档也没有帮助我。如果您能在这件事上给我建议,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

错误消息表明以下代码是错误的:

fun providesHomeViewModelFactory(providerMap: Map<Class<out ViewModel>, Provider<ViewModel>>): HomeViewModelFactory {
    return HomeViewModelFactory(providerMap)
}

应该是

fun providesHomeViewModelFactory(providerMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>): HomeViewModelFactory {
    return HomeViewModelFactory(providerMap)
}

这是因为Map接口的签名是Map<K, out V>,这意味着Map<..., Provider<ViewModel>>将被编译为Map<..., ? extends Provider<ViewModel>> Java代码,因此您要求匕首提供后者但是它的对象图中只有前一个,然后编译器会向您抛出错误。