ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常

Posted

技术标签:

【中文标题】ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常【英文标题】:Kotliin Dagger Field Injection in ViewModel Throws Dagger/Binding Exception 【发布时间】:2019-11-28 21:20:05 【问题描述】:

我已关注this tutorial,以便在我的视图模型中进行 DI。但我目前被卡住了。

我为我的视图模型创建了一个 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 构造函数。 Dagger 的文档也没有帮助我。如果您能就此问题给我建议,我将不胜感激。

【问题讨论】:

【参考方案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&lt;K, out V&gt;,这意味着Map&lt;..., Provider&lt;ViewModel&gt;&gt;将被编译成Map&lt;..., ? extends Provider&lt;ViewModel&gt;&gt;Java代码,所以你问匕首是后者,但它只有前者对象图,然后编译器会抛出错误。

【讨论】:

改成之后我仍然收到此错误。 error: [Dagger/MissingBinding] java.util.Map&lt;java.lang.Class&lt;? extends androidx.lifecycle.ViewModel&gt;,javax.inject.Provider&lt;androidx.lifecycle.ViewModel&gt;&gt; cannot be provided without an @Provides-annotated method. public abstract com.application.mvvmmusicplayer.ui.main.home.viewmodel.HomeViewModelFactory homeViewModelFactory(); 正如错误所说,您没有提供ViewModel 类,providesHomeViewModel 函数应该返回ViewModel 而不是HomeViewModel

以上是关于ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常的主要内容,如果未能解决你的问题,请参考以下文章

ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常

纯kotlin+ViewModel+LiveData+协程MVVM

Android : Kotlin : MVVM : 为啥 viewModel.onButtonClicked() 会导致应用程序崩溃?

如何将editText值传递给viewModel和Livedata(Kotlin)

Android - ViewModel、LiveData、Room 和 Retrofit 以及协程放在 kotlin 中

无法创建类 ViewModel kotlin 的实例